Can add shadowed_by_global to a site setting to override

If a site setting has `shadowed_by_global: true` then, if
a `GlobalSetting` exists with the same name then that value
will be used instead.  Additionally, the setting will be hidden.

This is useful in a multisite environment for private settings
such as API keys. You want to set it globally, yet not display
the key to customers.
This commit is contained in:
Robin Ward 2015-02-03 16:47:06 -05:00
parent 4c6c021b5c
commit aacf2e6f20
2 changed files with 85 additions and 3 deletions

View file

@ -46,6 +46,10 @@ module SiteSettingExtension
@choices ||= {}
end
def shadowed_settings
@shadowed_settings ||= []
end
def hidden_settings
@hidden_settings ||= []
end
@ -84,6 +88,15 @@ module SiteSettingExtension
hidden_settings << name
end
# You can "shadow" a site setting with a GlobalSetting. If the GlobalSetting
# exists it will be used instead of the setting and the setting will be hidden.
# Useful for things like API keys on multisite.
if opts[:shadowed_by_global] && GlobalSetting.respond_to?(name)
hidden_settings << name
shadowed_settings << name
current_value = GlobalSetting.send(name)
end
if opts[:refresh]
refresh_settings << name
end
@ -97,7 +110,7 @@ module SiteSettingExtension
end
current[name] = current_value
setup_methods(name, current_value)
setup_methods(name)
end
end
@ -133,7 +146,7 @@ module SiteSettingExtension
# Retrieve all settings
def all_settings(include_hidden=false)
@defaults
.reject{|s, _| hidden_settings.include?(s) || include_hidden}
.reject{|s, _| hidden_settings.include?(s) && !include_hidden}
.map do |s, v|
value = send(s)
type = types[get_data_type(s, value)]
@ -177,9 +190,11 @@ module SiteSettingExtension
if deletions.length > 0 || changes.length > 0
changes.each do |name, val|
next if shadowed_settings.include?(name)
current[name] = val
end
deletions.each do |name,val|
next if shadowed_settings.include?(name)
current[name] = defaults[name]
end
end
@ -364,7 +379,7 @@ module SiteSettingExtension
end
def setup_methods(name, current_value)
def setup_methods(name)
clean_name = name.to_s.sub("?", "")
eval "define_singleton_method :#{clean_name} do

View file

@ -339,4 +339,71 @@ describe SiteSettingExtension do
end
end
describe "hidden" do
before do
settings.setting(:superman_identity, 'Clark Kent', hidden: true)
settings.refresh!
end
it "is in the `hidden_settings` collection" do
settings.hidden_settings.include?(:superman_identity).should == true
end
it "can be retrieved" do
settings.superman_identity.should == "Clark Kent"
end
it "is not present in all_settings by default" do
settings.all_settings.find {|s| s[:setting] == :superman_identity }.should be_blank
end
it "is present in all_settings when we ask for hidden" do
settings.all_settings(true).find {|s| s[:setting] == :superman_identity }.should be_present
end
end
describe "shadowed_by_global" do
context "without global setting" do
before do
settings.setting(:trout_api_key, 'evil', shadowed_by_global: true)
settings.refresh!
end
it "should not add the key to the shadowed_settings collection" do
settings.shadowed_settings.include?(:trout_api_key).should == false
end
it "can return the default value" do
settings.trout_api_key.should == 'evil'
end
it "can overwrite the default" do
settings.trout_api_key = 'tophat'
settings.refresh!
settings.trout_api_key.should == 'tophat'
end
end
context "with global setting" do
before do
GlobalSetting.stubs(:trout_api_key).returns('purringcat')
settings.setting(:trout_api_key, 'evil', shadowed_by_global: true)
settings.refresh!
end
it "should return the global setting instead of default" do
settings.trout_api_key.should == 'purringcat'
end
it "should return the global setting after a refresh" do
settings.refresh!
settings.trout_api_key.should == 'purringcat'
end
it "should add the key to the shadowed_settings collection" do
settings.shadowed_settings.include?(:trout_api_key).should == true
end
end
end
end