(I agree with @user43685 and disagree with @Derek P -- there are lots of good reasons to keep site-wide data in the database instead of a yaml file. For example: your settings will be available on all web servers (if you have multiple web servers); changes to your settings will be ACID; you don't have to spend time implementing a YAML wrapper etc. etc.)
In rails, this is easy enough to implement, you just have to remember that your model should be a "singleton" in database terms, not in ruby object terms.
The easiest way to implement this is:
- Add a new model, with one column for each property you need
- Add a special column called "singleton_guard", and validate that it is always equal to "0", and mark it as unique (this will enforce that there is only one row in the database for this table)
- Add a static helper method to the model class to load the singleton row
So the migration should look something like this:
create_table :app_settings do |t|
t.integer :singleton_guard
t.datetime :config_property1
t.datetime :config_property2
...
t.timestamps
end
add_index(:app_settings, :singleton_guard, :unique => true)
And the model class should look something like this:
class AppSettings < ActiveRecord::Base
# The "singleton_guard" column is a unique column which must always be set to '0'
# This ensures that only one AppSettings row is created
validates_inclusion_of :singleton_guard, :in => [0]
def self.instance
# there will be only one row, and its ID must be '1'
begin
find(1)
rescue ActiveRecord::RecordNotFound
# slight race condition here, but it will only happen once
row = AppSettings.new
row.singleton_guard = 0
row.save!
row
end
end
end
In Rails >= 3.2.1 you should be able to replace the body of the "instance" getter with a call to "first_or_create!" like so:
def self.instance
first_or_create!(singleton_guard: 0)
end
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…