]> source.dussan.org Git - redmine.git/commitdiff
Added cache for application settings (Setting model).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Fri, 31 Aug 2007 17:45:32 +0000 (17:45 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Fri, 31 Aug 2007 17:45:32 +0000 (17:45 +0000)
Once the values are cached, only one database query is done at each user request (to check if the cache is still valid).

git-svn-id: http://redmine.rubyforge.org/svn/trunk@685 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/application.rb
app/models/setting.rb
db/migrate/065_add_settings_updated_on.rb [new file with mode: 0644]

index 1bb2eac0719227ce59c413703e00e58468e8b752..b1e2b3d7370c4ff741f83c6c1111a6f5bbd9ee69 100644 (file)
@@ -32,6 +32,7 @@ class ApplicationController < ActionController::Base
   end
   
   def user_setup
+    Setting.check_cache
     if session[:user_id]
       # existing session
       User.current = User.find(session[:user_id])
index ecca01c2825a4b6f1ff73aeb362f8340cc2ce1fe..c09b4bdb35e70bed78e450ae6a334ee4900fc350 100644 (file)
@@ -23,25 +23,28 @@ class Setting < ActiveRecord::Base
   validates_uniqueness_of :name
   validates_inclusion_of :name, :in => @@available_settings.keys
   validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| @@available_settings[setting.name]['format'] == 'int' }  
-  
-  def self.get(name)
-    name = name.to_s
-    setting = find_by_name(name)
-    setting ||= new(:name => name, :value => @@available_settings[name]['default']) if @@available_settings.has_key? name
-    setting
-  end
-  
+
+  # Hash used to cache setting values
+  @cached_settings = {}
+  @cached_cleared_on = Time.now
+    
+  # Returns the value of the setting named name
   def self.[](name)
-    get(name).value
+    value = @cached_settings[name]
+    value ? value : (@cached_settings[name] = find_or_default(name).value)
   end
   
   def self.[]=(name, value)
-    setting = get(name)
+    setting = find_or_default(name)
     setting.value = (value ? value.to_s : "")
+    @cached_settings[name] = nil
     setting.save
     setting.value
   end
   
+  # Defines getter and setter for each setting
+  # Then setting values can be read using: Setting.some_setting_name
+  # or set using Setting.some_setting_name = "some value"
   @@available_settings.each do |name, params|
     src = <<-END_SRC
     def self.#{name}
@@ -58,4 +61,26 @@ class Setting < ActiveRecord::Base
     END_SRC
     class_eval src, __FILE__, __LINE__
   end
+  
+  # Checks if settings have changed since the values were read
+  # and clears the cache hash if it's the case
+  # Called once per request
+  def self.check_cache
+    settings_updated_on = Setting.maximum(:updated_on)
+    if settings_updated_on && @cached_cleared_on <= settings_updated_on
+      @cached_settings.clear
+      @cached_cleared_on = Time.now
+      logger.info "Settings cache cleared." if logger
+    end
+  end
+  
+private
+  # Returns the Setting instance for the setting named name
+  # (record found in database or new record with default value)
+  def self.find_or_default(name)
+    name = name.to_s
+    raise "There's no setting named #{name}" unless @@available_settings.has_key?(name)    
+    setting = find_by_name(name)
+    setting ||= new(:name => name, :value => @@available_settings[name]['default']) if @@available_settings.has_key? name
+  end
 end
diff --git a/db/migrate/065_add_settings_updated_on.rb b/db/migrate/065_add_settings_updated_on.rb
new file mode 100644 (file)
index 0000000..8c5fde3
--- /dev/null
@@ -0,0 +1,11 @@
+class AddSettingsUpdatedOn < ActiveRecord::Migration
+  def self.up
+    add_column :settings, :updated_on, :timestamp
+    # set updated_on
+    Setting.find(:all).each(&:save)
+  end
+
+  def self.down
+    remove_column :settings, :updated_on
+  end
+end