You want a has_and_belongs_to_many
relationship. The guide does a great job of describing how this works with charts and everything:
http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association
You will end up with something like this:
# app/models/category.rb
class Category < ActiveRecord::Base
has_and_belongs_to_many :users
end
# app/models/user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :categories
end
Now you need to create a join table for Rails to use. Rails will not do this automatically for you. This is effectively a table with a reference to each of Categories and Users, and no primary key.
Generate a migration from the CLI like this:
bin/rails g migration CreateCategoriesUsersJoinTable
Then open it up and edit it to match:
For Rails 4.0.2+ (including Rails 5.2):
def change
# This is enough; you don't need to worry about order
create_join_table :categories, :users
# If you want to add an index for faster querying through this join:
create_join_table :categories, :users do |t|
t.index :category_id
t.index :user_id
end
end
Rails < 4.0.2:
def self.up
# Model names in alphabetical order (e.g. a_b)
create_table :categories_users, :id => false do |t|
t.integer :category_id
t.integer :user_id
end
add_index :categories_users, [:category_id, :user_id]
end
def self.down
drop_table :categories_users
end
With that in place, run your migrations and you can connect Categories and Users with all of the convenient accessors you’re used to:
User.categories #=> [<Category @name="Sports">, ...]
Category.users #=> [<User @name="UserA">, ...]
User.categories.empty?