This plugin allows attaching arbitrary set of attributes to a model, with inheritance. It is modeled after OpenStruct, for example:
user = User.create user.settings.language = 'en' user.settings.site_theme = 'green' user.settings.is_sidebar_hidden = true
script/plugin install git://github.com/invisiblellama/has_settings.git
Suppose you have global application-wide set of preferences and you want to be able to override some of these preferences for selected users or user groups.
1. Define a Setting model:
class Setting < ActiveRecord::Base acts_as_setting end
The structure of settings table is as follows:
create_table :settings do |t| t.integer :configurable_id t.string :configurable_type t.string :name, :limit => 40, :null => false t.string :value t.string :value_type end
This gives you access to global settings store:
Setting.global.some_setting = 42 Setting.global.some_other_setting = true
global is the default name of global settings accessor added by acts_as_setting to model, you can give it different name by passing parameter to acts_as_setting, f.i.:
2. Add settings to Group and User models:
Group model, inherits global settings from Setting
class Group < ActiveRecord::Base has_many :users has_settings :settings, :inherit => Setting end
User, inheriting from Group
class User < ActiveRecord::Base belongs_to :group has_settings :settings, :inherit => :group end
# set global 'site_theme' Setting.global.site_theme = 'default' Setting.global.site_theme # => 'default' # Group doesn't have 'site_theme' but it inherits from global settings, so group.settings.site_theme # => 'default' # so does User user.settings.site_theme # => 'default' # override 'site_theme' for the Group group.settings.site_theme = 'green' group.settings.site_theme # => 'green' # User inherits from the Group, so user.settings.site_theme # => 'green' # set 'site_theme' to nil to delete it group.settings.site_theme = nil # now both User and Group see global setting again user.settings.site_theme # => 'default' group.settings.site_theme # => 'default'
The interface is intentionally minimal. Assigning value to (almost arbitrary) named attribute will create named setting, assigning nil will delete it. Only simple types are supported:
boolean values (TrueClass, FalseClass)
Fixnum and Bignum
Time, Date, DateTime and ActiveSupport::TimeWithZone
Additionally, settings proxy provides a few public methods:
has_setting?(symbol_or_name, include_inherited = true)
will check if setting symbol_or_name is defined for the settings owner;
all(include_inherited = true)
will return all defined settings as a Hash. If include_inherited is set to false, only settings defined for the receiver will be checked and inheritance ignored.
And finally, key-value syntax is also supported:
group.settings['site_theme'] # same as group.settings.site_theme group.settings[:site_theme] = 'ponies' # same as group.settings.site_theme = 'ponies'
Copyright © 2009 Dmitri Goutnik, released under the MIT license.