开发者

Rails: Best practice to store user settings?

I'm wondering what the best way is to store user settings? For a web 2.0 app I want users to be able to select certain settings. At the moment is it only when to receive email notifications.

The easiest way would be to just create a Model "Settings" and have a column for every setting and then have a 1-1 relationship with users.

But is there a pattern to solve this better? Is it maybe better to store the info in the use开发者_Python百科r table itself? Or should I use a table with "settings_name" and "settings_value" to be completely open about the type of settings stored there (without having to run any migrations when adding options)?

What is your opinion?

Thanks


If you use PostgreSQL, the best solution is to use https://github.com/diogob/activerecord-postgres-hstore/. It's a simple, fast and reliable way to store hashes in the database. Since it's not just a serialised text field, you can search on it also, and you don't need to create a new table, as in HasEasy.

def User
  serialize :preferences, ActiveRecord::Coders::Hstore
end

user = User.create preferences: { theme: "navy" }
user.preferences['theme']


The "open" table approach makes it difficult to model with AR, since you have to worry about the types of the data (boolean, int, string, etc). I've always added prefs as columns on the users table, and then move them out to a user_preferences table if there are "too many" of them. It's simple, and it's easy to work with.


If the user settings are not meant to be findable (via a User.find_by_x_preference, e.g.) you could also store them in a serialized column as a hash. This is the use case described in the rails docs (http://www.railsbrain.com/api/rails-2.3.2/doc/index.html?a=M002334&name=serialize#), actually.

class User < ActiveRecord::Base
  serialize :preferences
end

u = User.new
u.preferences = {:favorite_color => "green", :favorite_book => "Moby Dick"}


We use the helpful plugin called HasEasy. It stores the data in a vertical table, but allows you to add validations, pre/post storage processing, types, etc.


Rails 6 supports ActiveRecordStore that can be used to solve this problem. The gem that improves ActiveRecordStore, by adding type definition, is activerecord-typedstore.

Define attributes in your model:

class User < ApplicationRecord
  typed_store :settings do |s|
    s.boolean :public, default: false, null: false
    s.string :email
    s.datetime :publish_at
    s.integer :age, null: false
  end
end

And use can use it:

shop = Shop.new(email: 'george@cyclim.se')
shop.public?        # => false
shop.email          # => 'george@cyclim.se'
shop.published_at   # => nil
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜