Rails: dynamic columns / attributes on models?

I have a SaaS application where accounts want to store different types of information in a user model. So, for example, one account may want to keep the age and date of birth, but in another account they will not use these columns and want to save information about hair color and height.

These are just examples, but how would I structure my model and db so that it works well with "custom, dynamic" columns without creating too many empty attributes.

+7
ruby database ruby-on-rails ruby-on-rails-4 database-design
source share
5 answers

For me, this sound, as a great example, you want to use the free NoSQL database, free from schema.

Or (if you want to stick with SQL), you can have a basic User model with has_many :attributes association. An attribute is just a combination of key ("age", "birthday", "hair color") and a value. Complexity comes with various data types and queries that span multiple attributes at once.

+5
source share

Here are two options. 1. NoSQL database. 2. Function Rails 4 Store .

+7
source share

If you use Postgresql, you can take a look at hstore, then you can save the information in a serialized form, and in fact you can make some requests for these hashes. btw Rails 4 has enabled this feature, but if you are using an older version of Rails, it may include this gem. https://github.com/diogob/activerecord-postgres-hstore in your Gemfile, and you should start playing like this:

 user = User.new user.preferences = { email: " p@elh.mx ", github: "heridev" } user.save! user.reload # Searching User.where("preferences @> hstore(:key, :value)", key: "email", value: " p@elh.mx ").first 
+1
source share

Your circuit might look like this:

 create_table "accounts", :force => true do |t| t.integer "user_id" t.string "data_key" t.string "data_value" end 

Account model

 belongs_to :user DATA_KEYS = ['age', 'birthdate', 'hair_color', 'height' ] # etc.. 

User model

 has_many :accounts Account::DATA_KEYS.each do |method| # getter method define_method(method) do accounts.find_by_data_key(method).try(:data_value) end # setter method define_method("#{method}=") do |value| data = accounts.find_or_initialize_by_data_key(method) data.data_value = value.strip data.save end end 

You can get and set account data values

eg. user.age => will return the age of the user

user.hair_color = 'brown' => set the hair color

0
source share

I would suggest moving to a NoSQL database. They are designed specifically for such cases, so you do not have to do crazy things to make everything work. MongoDB combined with MongoID is a very robust solution.

The only drawback may be hosting, as it is usually a little, at least, more expensive.

0
source share

All Articles