Module: Preferences::MacroMethods

Defined in:
lib/preferences.rb

Instance Method Summary collapse

Instance Method Details

#preference(name, *args) ⇒ Object

Defines a new preference for all records in the model. By default, preferences are assumed to have a boolean data type, so all values will be typecasted to true/false based on ActiveRecord rules.

Configuration options:

  • :default - The default value for the preference. Default is nil.

Examples

The example below shows the various ways to define a preference for a particular model.

class User < ActiveRecord::Base
  preference :notifications, :default => false
  preference :color, :string, :default => 'red'
  preference :favorite_number, :integer
  preference :data, :any # Allows any data type to be stored
end

All preferences are also inherited by subclasses.

Associations

After the first preference is defined, the following associations are created for the model:

  • stored_preferences - A collection of all the custom preferences specified for a record. This will not include default preferences unless they have been explicitly set.

Generated accessors

In addition to calling prefers? and preferred on a record, you can also use the shortcut accessor methods that are generated when a preference is defined. For example,

class User < ActiveRecord::Base
  preference :notifications
end

…generates the following methods:

  • prefers_notifications? - Whether a value has been specified, i.e. record.prefers?(:notifications)

  • prefers_notifications - The actual value stored, i.e. record.prefers(:notifications)

  • prefers_notifications=(value) - Sets a new value, i.e. record.set_preference(:notifications, value)

  • preferred_notifications? - Whether a value has been specified, i.e. record.preferred?(:notifications)

  • preferred_notifications - The actual value stored, i.e. record.preferred(:notifications)

  • preferred_notifications=(value) - Sets a new value, i.e. record.set_preference(:notifications, value)

Notice that there are two tenses used depending on the context of the preference. Conventionally, prefers_notifications? is better for accessing boolean preferences, while preferred_color is better for accessing non-boolean preferences.

Example:

user = User.find(:first)
user.prefers_notifications?         # => false
user.prefers_notifications          # => false
user.preferred_color?               # => true
user.preferred_color                # => 'red'
user.preferred_color = 'blue'       # => 'blue'

user.prefers_notifications = true

car = Car.find(:first)
user.preferred_color = 'red', car   # => 'red'
user.preferred_color(car)           # => 'red'
user.preferred_color?(car)          # => true

user.save!  # => true


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/preferences.rb', line 117

def preference(name, *args)
  unless included_modules.include?(InstanceMethods)
    class_inheritable_hash :preference_definitions
    self.preference_definitions = {}
    
    class_inheritable_hash :default_preferences
    self.default_preferences = {}
    
    has_many :stored_preferences, :as => :owner, :class_name => 'Preference'
    
    after_save :update_preferences
    
    include Preferences::InstanceMethods
  end
  
  # Create the definition
  name = name.to_s
  definition = PreferenceDefinition.new(name, *args)
  self.preference_definitions[name] = definition
  self.default_preferences[name] = definition.default_value
  
  # Create short-hand accessor methods, making sure that the name
  # is method-safe in terms of what characters are allowed
  name = name.gsub(/[^A-Za-z0-9_-]/, '').underscore
  
  # Query lookup
  define_method("preferred_#{name}?") do |*group|
    preferred?(name, group.first)
  end
  alias_method "prefers_#{name}?", "preferred_#{name}?"
  
  # Reader
  define_method("preferred_#{name}") do |*group|
    preferred(name, group.first)
  end
  alias_method "prefers_#{name}", "preferred_#{name}"
  
  # Writer
  define_method("preferred_#{name}=") do |*args|
    set_preference(*([name] + [args].flatten))
  end
  alias_method "prefers_#{name}=", "preferred_#{name}="
  
  definition
end