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
This commit is contained in:
Jean-Philippe Lang 2007-08-31 17:45:32 +00:00
parent 404bfce446
commit 6bdc13b33d
3 changed files with 47 additions and 10 deletions

View 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])

View 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

View File

@ -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