Settings plugin improvements
April 18th, 2006
This information is now old. A new version of the plugin can be found here with lots of instructions and examples.
Another Settings plugin update. This time there are 2 new features.
Store any object
The first is that all Settings are now stroed in the database as YAML, meaning any object may be stored, not just strings.
Settings.my_array = [1, '2', {:three => 3}]
Settings.my_array #=> [1, '2', {:three => 3}]
Settings.tax_rate = 0.0725
tax = @cart.total * Settings.tax_rate
NOTE: Old settings will not work with this version of the plugin. Each setting needs to be recreated through the console so that they are stored in YAML instead of plain text.
Default Settings
The next upgrade is that you can define default values without touching the database. This is useful for virgin installs of a reusable application. Just add something like the following to the bottom of environment.rb
module SettingsDefaults
DEFAULTS = {
:some_setting => 'abc',
:another_settings => 123
}
end
Then Setting.some_setting gives you back 'abc' even though its not in the database. If at anypoint in the future a custom value does get defined for some_setting the value in the database will be used instead.
ruby script/plugin install --force http://beautifulpixel.textdriven.com/svn/plugins/settings/
Also, I have 2 plugins I plan on extracting from a current project, ModelLogger and SuperImage. Stay tuned for more on those soon.
June 28th, 2007 at 11:05 PM
Great plugin! Nice improvements as well. I was just wondering if the migration for the settings table is still correct for YAML use:
t.column :value, :string, :null => true
should become IMHO:
t.column :value, :text, :null => true
Since you can store any object as a value, you’ll quickly run out of space with :string columns (MySQL limits these to 255 chars for example).
June 28th, 2007 at 11:05 PM
There is a bug in def self.[]=(var_name, value).
When you do something like: Settings.status_options = [‘retired’, ‘in use’, ‘in storage’, ‘broken’]
Then come back later and try to overwrite that setting with a different array: Settings.status_options = [‘i’,’am’,’a’,’dodo’]
Then it fails to write the update to the database.
The problem is that the line: if self[var_name] != value
compares self[var_name] in its already updated state to the new value. since the overall statement evaluated to false no database update is done.
I fixed it by commenting out 2 lines. I don’t see the need for this check anyways (is it for a tiny performance gain?)
#set a setting value by [] notation def self.[]=(var_name, value) #if self[var_name] != value var_name = var_name.to_s record = Settings.find(:first, :conditions => ['var = ?', var_name]) || Settings.new(:var => var_name) record.value = value.to_yaml record.save @@cache[var_name] = value # end endJune 28th, 2007 at 11:05 PM
The caching hash is a clever idea, but I wonder how it holds up across multiple fastcgi processes.
For example, what happens when one fastcgi process updates its hash and the database, while another process is still holding an old version of the hash?