Ruby on ZiGzAg About GitHub LinkedIn Twitter RSS

A Simple Global Setting class

10 Dec 2009 – Beijing

Almost in every web application, the administrator user need to setup some system parameters on the fly.
These parameter settings are different from the application configuration, which normally stored in the yml files under the config directory. Some of the developers incline to create a migration and store such properties into DB.

But for most of the simple situations, the YAML file just work fine. We only need to wrap it a little like a GlobalSetting class listed below.

So that you can save your params got from controller directly like:
GlobalSetting.save param[:setting]

And retrieve them just by:
GlobalSetting[:TAX_RATE]

The setting hash you save can have more complex structure combined by arrays or other hashes,like:
GlobalSetting.save {:ACCOUNT => {:TAX_RATE => 0.2}}

Instead of using
GlobalSetting[:ACCOUNT] && GlobalSetting[:ACCOUNT][:TAX_RATE]
for avoiding the NoMethodError, we have a more DRY way:
GlobalSetting[:ACCOUNT, :TAX_RATE].

Source Code of global_setting.rb

class GlobalSetting
  cattr_accessor :file_path
  self.file_path = File.join(RAILS_ROOT,'config','setting.yml')
  
  def self.[](*keys)
    keys.inject(setting){ |m,k| m[k] if m.is_a?(Array) || m.is_a?(Hash)}
  end
  
  def self.[]=(key,value)
    setting[key] = value
  end

  def self.save(hash = nil)
    hash = setting unless hash
    File.open(file_path,'w+'){|f| f << hash.to_yaml}
    @setting = load
  end

  def self.merge(hash)
    setting.merge!(hash)
    save
  end
  
  private
  def self.setting
    @setting ||= load 
  end
  
  def self.load
    File.file?(file_path) ? YAML.load_file(file_path) : {}
  end
end

The Unit Test Code showing how to use it

class GlobalSettingTest < ActiveSupport::TestCase
  def setup
    GlobalSetting.file_path = File.join(RAILS_ROOT,'tmp','test_setting.yml')
    GlobalSetting.save :t1 => "v1",:t2 => "v2",:arr => ['a1','a2',3],
                       :h1 => {:nh => "nested" }
  end
  def test_load
    assert_equal("v1", GlobalSetting[:t1])
    assert_equal("v2", GlobalSetting[:t2])
    assert_equal(3, GlobalSetting[:arr][2])
  end
  def test_update
    assert_equal("v1", GlobalSetting[:t1])
    GlobalSetting[:t1] ="c1"
    GlobalSetting.save
    assert_equal("c1", GlobalSetting[:t1])
  end
  def test_load_from_top
    assert_equal("v1", GlobalSetting[][:t1])
  end
  def test_dig
    assert_equal(3, GlobalSetting[:arr,2])
    assert_equal("nested", GlobalSetting[:h1,:nh])
    assert_nil(GlobalSetting[:t1,:foo,:bar])
    assert_nil(GlobalSetting[:arr,2,:dd])
  end
  def test_merge
    GlobalSetting.merge({:h1 => "new Value"})
    assert_equal("v1", GlobalSetting[:t1])
    assert_equal("new Value", GlobalSetting[:h1])
  end
end

Comments

Fork me on GitHub