From: Jean-Philippe Lang Date: Fri, 31 Aug 2007 17:45:32 +0000 (+0000) Subject: Added cache for application settings (Setting model). X-Git-Tag: 0.6.0~197 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6bdc13b33d8d8d2052d029ac8f99ad0f62df6211;p=redmine.git Added cache for application settings (Setting model). 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 --- diff --git a/app/controllers/application.rb b/app/controllers/application.rb index 1bb2eac07..b1e2b3d73 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -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]) diff --git a/app/models/setting.rb b/app/models/setting.rb index ecca01c28..c09b4bdb3 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -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 index 000000000..8c5fde33b --- /dev/null +++ b/db/migrate/065_add_settings_updated_on.rb @@ -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