Stop using global vars where not needed

Simplify local process site setting provider
Stop setting up methods over and over
Centralize cache clearing
This commit is contained in:
Sam 2014-03-28 16:36:17 +11:00
parent 64b0d7e0ea
commit 8fc2549873
4 changed files with 110 additions and 35 deletions

View File

@ -23,7 +23,7 @@ class SiteSetting < ActiveRecord::Base
load_settings(file) load_settings(file)
end end
SiteSettingExtension.class_variable_get(:@@client_settings) << :available_locales client_settings << :available_locales
def self.available_locales def self.available_locales
LocaleSiteSetting.values.map{ |e| e[:value] }.join('|') LocaleSiteSetting.values.map{ |e| e[:value] }.join('|')

View File

@ -22,8 +22,8 @@ module SiteSettingExtension
end end
def current def current
@@containers ||= {} @containers ||= {}
@@containers[provider.current_site] ||= {} @containers[provider.current_site] ||= {}
end end
def defaults def defaults
@ -62,6 +62,8 @@ module SiteSettingExtension
if opts[:refresh] == true if opts[:refresh] == true
refresh_settings << name refresh_settings << name
end end
current[name] = current_value
setup_methods(name, current_value) setup_methods(name, current_value)
end end
end end
@ -69,12 +71,12 @@ module SiteSettingExtension
# just like a setting, except that it is available in javascript via DiscourseSession # just like a setting, except that it is available in javascript via DiscourseSession
def client_setting(name, default = nil, opts = {}) def client_setting(name, default = nil, opts = {})
setting(name, default, opts) setting(name, default, opts)
@@client_settings ||= [] @client_settings ||= []
@@client_settings << name @client_settings << name
end end
def client_settings def client_settings
@@client_settings @client_settings ||= []
end end
def settings_hash def settings_hash
@ -92,7 +94,7 @@ module SiteSettingExtension
end end
def client_settings_json_uncached def client_settings_json_uncached
MultiJson.dump(Hash[*@@client_settings.map{|n| [n, self.send(n)]}.flatten]) MultiJson.dump(Hash[*@client_settings.map{|n| [n, self.send(n)]}.flatten])
end end
# Retrieve all settings # Retrieve all settings
@ -125,24 +127,24 @@ module SiteSettingExtension
ensure_listen_for_changes ensure_listen_for_changes
old = current old = current
all_settings = provider.all new_hash = Hash[*(provider.all.map{ |s|
new_hash = Hash[*(all_settings.map{|s| [s.name.intern, convert(s.value,s.data_type)]}.to_a.flatten)] [s.name.intern, convert(s.value,s.data_type)]
}.to_a.flatten)]
# add defaults # add defaults, cause they are cached
new_hash = defaults.merge(new_hash) new_hash = defaults.merge(new_hash)
changes,deletions = diff_hash(new_hash, old) changes,deletions = diff_hash(new_hash, old)
if deletions.length > 0 || changes.length > 0 if deletions.length > 0 || changes.length > 0
@current = new_hash
changes.each do |name, val| changes.each do |name, val|
setup_methods name, val current[name] = val
end end
deletions.each do |name,val| deletions.each do |name,val|
setup_methods name, defaults[name] current[name] = defaults[name]
end end
end end
clear_cache!
Rails.cache.delete(SiteSettingExtension.client_settings_cache_key)
end end
end end
@ -176,16 +178,18 @@ module SiteSettingExtension
end end
def process_id def process_id
@@process_id ||= SecureRandom.uuid @process_id ||= SecureRandom.uuid
end end
def after_fork def after_fork
@@process_id = nil @process_id = nil
ensure_listen_for_changes
end end
def remove_override!(name) def remove_override!(name)
provider.destroy(name) provider.destroy(name)
current[name] = defaults[name] current[name] = defaults[name]
clear_cache!
end end
def add_override!(name,val) def add_override!(name,val)
@ -208,6 +212,9 @@ module SiteSettingExtension
end end
provider.save(name, val, type) provider.save(name, val, type)
current[name] = convert(val, type)
clear_cache!
@last_message_sent = MessageBus.publish('/site_settings', {process: process_id}) @last_message_sent = MessageBus.publish('/site_settings', {process: process_id})
end end
@ -230,6 +237,10 @@ module SiteSettingExtension
protected protected
def clear_cache!
Rails.cache.delete(SiteSettingExtension.client_settings_cache_key)
end
def diff_hash(new_hash, old) def diff_hash(new_hash, old)
changes = [] changes = []
deletions = [] deletions = []
@ -277,14 +288,16 @@ module SiteSettingExtension
def setup_methods(name, current_value) def setup_methods(name, current_value)
# trivial multi db support, we can optimize this later
current[name] = current_value
clean_name = name.to_s.sub("?", "") clean_name = name.to_s.sub("?", "")
eval "define_singleton_method :#{clean_name} do eval "define_singleton_method :#{clean_name} do
c = @@containers[provider.current_site] c = @containers[provider.current_site]
c = c[name] if c if c
c c[name]
else
refresh!
current[name]
end
end end
define_singleton_method :#{clean_name}? do define_singleton_method :#{clean_name}? do
@ -293,7 +306,6 @@ module SiteSettingExtension
define_singleton_method :#{clean_name}= do |val| define_singleton_method :#{clean_name}= do |val|
add_override!(:#{name}, val) add_override!(:#{name}, val)
refresh!
end end
" "
end end

View File

@ -2,34 +2,37 @@ module SiteSettings; end
class SiteSettings::LocalProcessProvider class SiteSettings::LocalProcessProvider
attr_accessor :current_site
Setting = Struct.new(:name, :value, :data_type) unless defined? SiteSettings::LocalProcessProvider::Setting Setting = Struct.new(:name, :value, :data_type) unless defined? SiteSettings::LocalProcessProvider::Setting
def initialize(defaults = {}) def settings
@settings = {} @settings[current_site] ||= {}
@defaults = {}
defaults.each do |name,(value,data_type)|
@defaults[name] = Setting.new(name,value,data_type)
end end
def initialize()
@settings = {}
self.current_site = "test"
end end
def all def all
(@defaults.merge @settings).values settings.values
end end
def find(name) def find(name)
@settings[name] || @defaults[name] settings[name]
end end
def save(name, value, data_type) def save(name, value, data_type)
@settings[name] = Setting.new(name,value, data_type) settings[name] = Setting.new(name,value, data_type)
end end
def destroy(name) def destroy(name)
@settings.delete(name) settings.delete(name)
end end
def current_site def clear
"test" @settings[current_site] = {}
end end
end end

View File

@ -6,13 +6,73 @@ describe SiteSettingExtension do
class FakeSettings class FakeSettings
extend SiteSettingExtension extend SiteSettingExtension
provider = SiteSettings::LocalProcessProvider self.provider = SiteSettings::LocalProcessProvider.new
end
class FakeSettings2
extend SiteSettingExtension
self.provider = FakeSettings.provider
end end
let :settings do let :settings do
FakeSettings FakeSettings
end end
let :settings2 do
FakeSettings2
end
describe "refresh!" do
it "will reset to default if provider vanishes" do
settings.setting(:hello, 1)
settings.hello = 100
settings.hello.should == 100
settings.provider.clear
settings.refresh!
settings.hello.should == 1
end
it "will set to new value if provider changes" do
settings.setting(:hello, 1)
settings.hello = 100
settings.hello.should == 100
settings.provider.save(:hello, 99, SiteSetting.types[:fixnum] )
settings.refresh!
settings.hello.should == 99
end
it "Publishes changes cross sites" do
settings.setting(:hello, 1)
settings2.setting(:hello, 1)
settings.hello = 100
settings2.refresh!
settings2.hello.should == 100
settings.hello = 99
settings2.refresh!
settings2.hello.should == 99
end
end
describe "multisite" do
it "has no db cross talk" do
settings.setting(:hello, 1)
settings.hello = 100
settings.provider.current_site = "boom"
settings.hello.should == 1
end
end
describe "int setting" do describe "int setting" do
before do before do
settings.setting(:test_setting, 77) settings.setting(:test_setting, 77)