Last Updated: February 25, 2016
·
1.841K
· alii

Multiple HABTM associations between 2 models in Rails

There can be a case where you want to have more than one has_and_belongs_to_many associations between 2 models.
Here I will show you how to achieve this and write some specs.

Consider following case: There are services (like cleaning, fixing stuff). A service has providers and seekers, both of which are Users.

# spec/models/service_spec.rb
require 'rails_helper'

describe Service do
 describe 'associations' do
 it { is_expected.to have_and_belong_to_many(:providers)
 .class_name('User') }
 it { is_expected.to have_and_belong_to_many(:seekers)
 .class_name('User') }
 end
end

There are users. A user can provide and look for services.

# spec/models/user_spec.rb
require 'rails_helper'

describe User do
 describe 'associations' do
 it { is_expected.to have_and_belong_to_many(:provides)
 .class_name('Service') }
 it { is_expected.to have_and_belong_to_many(:seeks)
 .class_name('Service') }
 end
end

For this we'll need 2 more tables. One join table for providers, another for seekers. Here's our migration:

# db/migrate/20140807005921_join_providers_seekers_services.rb
class JoinProvidersSeekersServices < ActiveRecord::Migration
 def change
 create_table :providers_services do |t|
 t.references :user, index: true
 t.references :service, index: true

 t.timestamps
 end

 create_table :seekers_services do |t|
 t.references :user, index: true
 t.references :service, index: true

 t.timestamps
 end
 end
end

And now we can join our 2 models in multiple has_and_belongs_to_many associations:

# app/models/service.rb
class Service < ActiveRecord::Base
 has_and_belongs_to_many :seekers, join_table: 'seekers_services',
 class_name: 'User'
 has_and_belongs_to_many :providers, join_table: 'providers_services',
 class_name: 'User'
end
# app/models/user.rb
class User < ActiveRecord::Base
 has_and_belongs_to_many :seeks, join_table: 'seekers_services',
 class_name: 'Service'
 has_and_belongs_to_many :provides, join_table: 'providers_services',
 class_name: 'Service'
end

Specs are written with rspec-rails 3 and shoulda-matchers.

Original post: http://alii.pro/blog/2014/08/16/multiple-habtm-associations/

1 Response
Add your response

Hi,
Can you tell me how to do it for below tables? I have 2 tables.
1. products
2. coupon_codes

Now, i want to add include products and exclude products in create coupon code page so i need HABTM relationship table with above 2 tables.

How can i do it?

over 1 year ago ·