Adds support for easily creating custom preferences for models
Switch branches/tags
Pull request Compare This branch is 2 commits ahead, 56 commits behind pluginaweek:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



preferences adds support for easily creating custom preferences for models.






  • git://


Preferences for models within an application, such as for users, is a pretty common idiom. Although the rule of thumb is to keep the number of preferences available to a minimum, sometimes it's necessary if you want users to be able to disable things like e-mail notifications.

Generally, basic preferences can be accomplished through simple designs, such as additional columns or a bit vector described and implemented by preference_fu. However, as you find the need for non-binary preferences and the number of preferences becomes unmanageable as individual columns in the database, the next step is often to create a separate “preferences” table. This is where the preferences plugin comes in.

preferences encapsulates this design by hiding the fact that preferences are stored in a separate table and making it dead-simple to define and manage preferences.


Defining preferences

To define the preferences for a model, you can do so right within the model:

class User < ActiveRecord::Base
  preference :hot_salsa
  preference :dark_chocolate, :default => true
  preference :color, :string
  preference :favorite_number
  preference :language, :string, :default => 'English'

In the above model, 5 preferences have been defined:

  • hot_salsa

  • dark_chocolate

  • color

  • favorite_number

  • language

For each preference, a data type and default value can be specified. If no data type is given, it's considered a boolean value. If no default value is given, the default is assumed to be nil.

Accessing preferences

Once preferences have been defined for a model, they can be accessed either using the shortcut methods that are generated for each preference or the generic methods that are not specific to a particular preference.

Shortcut methods

There are several shortcut methods that are generated. They are shown below.

Query methods:

user.prefers_hot_salsa?         # => false
user.prefers_dark_chocolate?    # => false

Reader methods:

user.preferred_color      # => nil
user.preferred_language   # => "English"

Writer methods:

user.prefers_hot_salsa = false        # => false
user.preferred_language = 'English'   # => "English"

Generic methods

Each shortcut method is essentially a wrapper for the various generic methods shown below:

Query method:

user.prefers?(:hot_salsa)       # => false
user.prefers?(:dark_chocolate)  # => false

Reader method:

user.preferred(:color)      # => nil
user.preferred(:language)   # => "English"

Write method:

user.set_preference(:hot_salsa, false)      # => false
user.set_preference(:language, "English")   # => "English"

Accessing all preferences

To get the collection of all custom, stored preferences for a particular record, you can access the stored_preferences has_many association which is automatically generated:


In addition to this, you can get a hash of all stored preferences and default preferences, by accessing the preferences helper:

user.preferences  # => {"language"=>"English", "color"=>nil}

This hash will contain the value for every preference that has been defined for the model, whether that's the default value or one that has been previously stored.

A short-hand alternative for preferences is also available:

user.prefs  # => {"language"=>"English", "color"=>nil}

Grouping preferences

In addition to defining generic preferences for the owning record, you can also group preferences by ActiveRecord objects or arbitrary names. This is best shown through an example:

user = User.find(:first)
car = Car.find(:first)

user.preferred_color = 'red', car
# user.set_preference(:color, 'red', car) # The generic way

This will create a preference for the color “red” for the given car. In this way, you can have “color” preferences for different records.

To access the preference for a particular record, you can use the same accessor methods as before:

# user.preferred(:color, car) # The generic way

In addition to grouping preferences for a particular record, you can also group preferences by name. For example,

user = User.find(:first)

user.preferred_color = 'red', 'automobiles'
user.preferred_color = 'tan', 'clothing'

user.preferred_color('automobiles')   # => "red"
user.preferred_color('clothing')      # => "tan"

user.preferences                # => {"color"=>nil, "automobiles"=>{"color"=>"red"}, "clothing=>{"color=>"tan"}}
user.preferences('automobiles') # => {"color"=>"red"}

Saving preferences

Note that preferences are not saved until the owning record is saved. Preferences are treated in a similar fashion to attributes. For example,

user = user.find(:first)
user.attributes = {:preferred_color => 'red'}!

Preferences are stored in a separate table called “preferences”.


Before you can run any tests, the following gem must be installed:

To run against a specific version of Rails:

rake test RAILS_FRAMEWORK_ROOT=/path/to/rails


  • Rails 2.1 or later

  • plugins_plus (optional if app files are copied to your project tree)