vendor/plugins/refinery_settings/app/models/refinery_setting.rb in refinerycms-0.9.6.34 vs vendor/plugins/refinery_settings/app/models/refinery_setting.rb in refinerycms-0.9.7

- old
+ new

@@ -1,16 +1,37 @@ class RefinerySetting < ActiveRecord::Base validates_presence_of :name serialize :value # stores into YAML format + serialize :callback_proc_as_string # Number of settings to show per page when using will_paginate def self.per_page 12 end + after_save do |setting| + if self.column_names.include?('scoping') + cache_write(setting.name, setting.scoping.presence, setting.value) + else + cache_write(setting.name, nil, setting.value) + end + end + + def self.cache_key(name, scoping) + "#{Refinery.base_cache_key}_refinery_setting_#{name}#{"_with_scoping_#{scoping}" if scoping.present?}" + end + + def self.cache_read(name, scoping) + Rails.cache.read(cache_key(name, scoping)) + end + + def self.cache_write(name, scoping, value) + Rails.cache.write(cache_key(name, scoping), value) + end + # prettier version of the name. # site_name becomes Site Name def title self.name.titleize end @@ -28,34 +49,66 @@ else self[method_name] end end - def self.find_or_set(name, the_value) - find_or_create_by_name(:name => name.to_s, :value => the_value).value + def self.find_or_set(name, the_value, options={}) + # Try to get the value from cache first. + scoping = options[:scoping] + restricted = options[:restricted] + callback_proc_as_string = options[:callback_proc_as_string] + if (value = cache_read(name, scoping)).nil? + setting = find_or_create_by_name(:name => name.to_s, :value => the_value) + + # if the database is not up to date yet then it won't know about certain fields. + setting.scoping = scoping if self.column_names.include?('scoping') + setting.restricted = restricted if self.column_names.include?('restricted') + setting.callback_proc_as_string = callback_proc_as_string if callback_proc_as_string.is_a?(String) && self.column_names.include?('callback_proc_as_string') + + setting.save + + # cache whatever we found including its scope in the name, even if it's nil. + cache_write(name, scoping, (value = setting.try(:value))) + end + + # Return what we found. + value end def self.[](name) - setting = self.find_by_name(name.to_s) - setting.value unless setting.nil? + # Try to get the value from cache first. + if (value = cache_read(name, (scoping = nil))).nil? + # Not found in cache, try to find the record itself and cache whatever we find. + value = cache_write(name, scoping, self.find_by_name(name.to_s).try(:value)) + end + + # Return what we found. + value end def self.[]=(name, value) setting = find_or_create_by_name(name.to_s) - setting.value = value + + # you could also pass in {:value => 'something', :scoping => 'somewhere'} + unless value.is_a?(Hash) and value.has_key?(:value) + setting.value = value + else + setting.value = value[:value] + setting.scoping = value[:scoping] if value.has_key?(:scoping) and setting.class.column_names.include?('scoping') + setting.callback_proc_as_string = value[:callback_proc_as_string] if value.has_key?(:callback_proc_as_string) and setting.class.column_names.include?('callback_proc_as_string') + end + setting.save end # Below is not very nice, but seems to be required - # The problem is when Rails serialises a fields like booleans - # it doesn't retreieve it back out as a boolean - # it just returns a string. This code maps the two boolean - # values correctly so a boolean is returned + # The problem is when Rails serialises a fields like booleans it doesn't retrieve it back out as a boolean + # it just returns a string. This code maps the two boolean values correctly so a boolean is returned REPLACEMENTS = {"true" => true, "false" => false} def value - if (current_value = self[:value]).present? + unless (current_value = self[:value]).nil? # This bit handles true and false so that true and false are actually returned # not "0" and "1" REPLACEMENTS.each do |current, new_value| current_value = new_value if current_value == current end @@ -76,8 +129,12 @@ def value=(new_value) # must convert to string if true or false supplied otherwise it becomes 0 or 1, unfortunately. new_value = new_value.to_s if ["trueclass","falseclass"].include?(new_value.class.to_s.downcase) self[:value] = new_value + end + + def callback_proc + eval "Proc.new{#{self.callback_proc_as_string} }" if RefinerySetting.column_names.include?('callback_proc_as_string') && self.callback_proc_as_string.present? end end