UserPreferences

An ActiveRecord backed user preference library that supports:

  • Categories (currently non-optional)
  • Binary and non-binary preferences
  • Default values
  • Value validation
  • Retrieving users scoped by a particular preference

Installation

Add this line to your application's Gemfile:

gem 'user_preferences'

And then execute:

$ bundle

Run the installation script:

$ rails g user_preferences:install

This will copy across the migration and add an empty preference definition file in config/

Finally, run the database migrations:

$ rake db:migrate

Defining preferences

Your preferences are defined in config/user_preferences.yml. You define each of your preferences within a category. This example definition for a binary preference implies that users receive emails notifications by default but not newsletters:

emails:
  notifications: true
  newsletters: false

You can configure non-binary preferences. For example, if users could choose periodical notification digests, the configuration might look like this:

emails:
  notifications:
    default: instant
    values:
      - off
      - instant
      - daily
      - weekly
  newsletters: false

You can add as many categories as you like:

emails:
  notifications: true
  newsletters: false

beta_features:
  two_factor_authentication: false
  the_big_red_button: false

API

set

Similar to ActiveRecord, setting a preference returns true or false depending on whether or not it was successfully persisted:

user.preferences(:emails).set(notifications: 'instant') # => true
user.preferences(:emails).set(notifications: 'some_typo') # => false

You can set multiple preferences at once:

user.preferences(:emails).set(notifications: 'instant', newsletter: true) # => true

get

A single preference:

user.preferences(:emails).get(:notifications) # => 'instant'

all

All preferences for a category:

user.preferences(:emails).all # => { notifications: 'instant', newsletter: true }

reload

Reload the preferences from the database; since something else might have changed the user's state.

user.preferences(:emails).reload # => { notifications: 'instant', newsletter: true }

Scoping users

  newsletter_users = User.with_preference(:email, :newsletter, true) #=> an ActiveRecord::Relation

Note: this will include users who have not overriden the default value if the value incidentally matches the default value.

Other useful stuff

Single preference definition

  • Get your preference definition (as per your .yml) as a hash: UserPreferences.definitions
  • Get the definition for a single preference: ruby preference = UserPreferences[:emails, :notifications] preference.default # => 'instant' preference.binary? # => false preference.permitted_values # => ['off', 'instant', 'daily', 'weekly']
  • Retrieve the default preference state with UserPreferences.defaults. You can also scope to a category: UserPreferences.defaults(:emails)

Testing

$ rake test

Contributing

  1. Fork it ( http://github.com/mubi/user_preferences/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request