0
\$\begingroup\$

I have a model Users that each instance have 3 features. It was alright until I wanted to tell if this instance can do the 1st feature, the 3rd or all.

I did a migration:

class AddStatusFeaturesToUsers < ActiveRecord::Migration
  def change
    add_column :users, :status_feature_a, :boolean
    add_column :users, :status_feature_b, :boolean
    add_column :users, :status_feature_c, :boolean
  end
end

Is there a better way for doing this?

\$\endgroup\$
5
  • \$\begingroup\$ Do you want us to review you migration code or the Users class that you haven't posted? \$\endgroup\$ Dec 12, 2014 at 17:38
  • \$\begingroup\$ I was wondering where I can ask what the best solution and I though this was the best place \$\endgroup\$
    – Charlon
    Dec 12, 2014 at 17:40
  • \$\begingroup\$ I don't understand what your concern is. Could you please edit the question with more details to clarify it? \$\endgroup\$ Dec 12, 2014 at 17:44
  • \$\begingroup\$ If you are looking for one line solution, then it is not possible. \$\endgroup\$ Dec 14, 2014 at 5:23
  • \$\begingroup\$ What is a feature, given your scope? \$\endgroup\$
    – D-side
    Dec 21, 2014 at 14:47

2 Answers 2

2
\$\begingroup\$

If your user and features model can have a many-to-many relationship, then you can use the following example:

A has_and_belongs_to_many association creates a direct many-to-many connection with another model, with no intervening model

class CreateUsersAndStatusFeatures < ActiveRecord::Migration
  def change
    create_table :status_features do |t|
      t.string :name
      t.timestamps null: false
    end
    # Do not create users table if you already have.
    create_table :users do |t|
      t.string :name
      t.timestamps null: false
    end
    create_table :users_status_features, id: false do |t|
      t.belongs_to :user, index: true
      t.belongs_to :status_feature, index: true
    end
  end
end

class User < ActiveRecord::Base
  has_and_belongs_to_many :status_features
end
class StatusFeature < ActiveRecord::Base
  has_and_belongs_to_many :users
end

If you want to know in detail, go to this link.

\$\endgroup\$
0
\$\begingroup\$

There are a couple of options available and you need to choose which one is suitable for your problem.

  1. Has And Belongs To Many association

    This has been covered by @Cba Bhusal's answer. The downside of this approach is that it will require extra query to DB each time you want to check status of a features. It's not always suitable.

  2. Embeed feature field if User model as bitmask.

    Check this railscast for more information how it works.

    The downside is that there is limit of how many features you can have this way and you are not allowed to change order or remove the features.

  3. Use separate field in user model for each feature

    This is you approach. It's fine only if you have few features and do not plan to add more, otherwise choose something else.

  4. Add single text field to user model and serialize features to i.e. JSON

    This gives you pretty much best extensibility with almost zero performance cost.

    The downside is querying users by features - database won't understand serialized text field. If you need to do this there is a chance that your database supports data type you are serializing to, i.e. Postgres works fine with JSON or Array data types and Rails can take advantage of it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.