Plugins - preferences

StarAdd to favorites

preferences

preferences adds support for easily creating custom preferences for models.

Resources

API

Bugs

Development

Source

  • git://github.com/pluginaweek/preferences.git

Description

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[http://agilewebdevelopment.com/plugins/preferencefu]. 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.

Usage

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'
  end

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:

  user.stored_preferences

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.

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)
  # 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'}
  user.save!

Preferences are stored in a separate table called "preferences".

Testing

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

Dependencies

Aaron Pfeifer

http://github.com/pluginaweek/preferences

git://github.com/pluginaweek/preferences.git

Rails' (MIT)

  • Currently 3.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Model

Tags

Comments

Add a comment
Aaron Pfeifer 13 May 2008

FYI, I've added information to the README about testing specific versions of Rails, as well as the Rails version that the plugin depends on.

Aaron Pfeifer 13 May 2008

Thanks for the comments.

Brennan - Thanks for the heads up, wasn't aware of that one.

Christopher- Interesting, I should note in the documentation that some of these plugins only work as plugins (plugins_plus in this case).

I'm going to guess that you're not running Rails 2.1, which is what these plugins are developed for. If you want to run this on Rails 2.0, you may have better luck dropping plugins_plus and copying the models/migrations over to your application. If you do have an edge version of Rails running, you can test it like so:

rake test RAILSFRAMEWORKROOT=/path/to/rails/edge

I'll add that to the docs.

Come by the pluginaweek-talk Google Group if you have any questions!

Christopher J. Bottaro 12 May 2008

Hey, Cool looking plugin, but I can't get 'rake test' to work (from the plugin dir). I installed pluginsplus and plugintesthelper via gem and preferences via script/plugin and it didn't work. Then I installed pluginsplus and plugintesthelper from script/plugin (so now all 3 are installed that way) and I get this error:

/Users/cjbottaro/Work/tragence-preferences/vendor/plugins/preferences/test/approot/config/../../../../pluginsplus/lib/pluginsplus/appintegration.rb:50:in app_load_paths': undefined methodconfiguration' for Rails:Module (NoMethodError)

Also, just from perusing the source, it seems like self.preference_definitions = {attribute => definition} should be self.preference_definitions[attribute] = definition (from MacroMethods#preference)

That's why I was trying to get the test running.

Brennan Dunn 11 May 2008

Very nice, Aaron! I quickly realized that my preference_fu plugin just didn't do what I needed (non boolean, hard to redefine / remove in production mode.)

I developed http://github.com/brennandunn/configurator/tree/master as a replacement, which seems to be pretty similar to preferences.

Search Plugins

Query syntax

Plugins by Category

Sponsors

Rails Kits: Get Code. Get Moving.

Have a comment?