This is a complete sample on how to create many to many association using has_many :throght
for this example i use staff
model and client
model where staff has many client and client has many staff
In your terminal type below
$ rails new many-to-many
$ cd many-to-many
$ bundle install
$ rails server
$ rails generate scaffold Staff full_name:string position:string
$ rails generate scaffold Client full_name:string business_name:string
$ rails generate model relationship
after typing terminal open db/migrate/xxxxxxxxxxxxxx_create_relationships.rb
add this code
t.belongs_to :client, index: true
t.belongs_to :staff, index: true
class CreateRelationships < ActiveRecord::Migration
def change
create_table :relationships do |t|
t.belongs_to :client, index: true
t.belongs_to :staff, index: true
t.timestamps null: false
end
end
end
after adding the table column to the relationship table
run this to your terminal
$ rake db:migrate
and after finishing the migration
open
app/models/staff.rb
app/models/client.rb
app/models/relationship.rb
inside the app/models/staff.rb
add this code
has_many :relationships
has_many :clients, :through => :relationships
it will be something like this
class Staff < ActiveRecord::Base
has_many :relationships
has_many :clients, :through => :relationships
end
and inside the app/models/client.rb
has_many :relationships
has_many :staffs, :through => :relationships
it will be something like this
class Client < ActiveRecord::Base
has_many :relationships
has_many :staffs, :through => :relationships
end
then inside the app/models/relationship.rb
add
belongs_to :staff
belongs_to :client
it should be look like this
class Relationship < ActiveRecord::Base
belongs_to :staff
belongs_to :client
end
Next we will configure the view form both the staff
and client
Open
app/views/clients/_form.html.erb
app/views/staffs/_form.html.erb
At this point we are using checkbox to select associations
open app/views/clients/_form.html.erb
add this to the form
<%= hidden_field_tag "client[staff_ids][]", nil %>
<% Staff.all.each do |staff| %>
<%= check_box_tag "client[staff_ids][]", staff.id, @client.staff_ids.include?(staff.id), id: dom_id(staff) %>
<%= label_tag dom_id(staff), staff.full_name %><br>
<% end %>
It will be something like this
<%= form_for(@client) do |f| %>
<% if @client.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@client.errors.count, "error") %> prohibited this client from being saved:</h2>
<ul>
<% @client.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :full_name %><br>
<%= f.text_field :full_name %>
</div>
<div class="field">
<%= f.label :business_name %><br>
<%= f.text_field :business_name %>
</div>
<%= hidden_field_tag "client[staff_ids][]", nil %>
<% Staff.all.each do |staff| %>
<%= check_box_tag "client[staff_ids][]", staff.id, @client.staff_ids.include?(staff.id), id: dom_id(staff) %>
<%= label_tag dom_id(staff), staff.full_name %><br>
<% end %>
<br>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Then do it also on staff form
open app/views/staffs/_form.html.erb
add this
<%= hidden_field_tag "staff[client_ids][]", nil %>
<% Client.all.each do |client| %>
<%= check_box_tag "staff[client_ids][]", client.id, @staff.client_ids.include?(client.id), id: dom_id(client) %>
<%= label_tag dom_id(client), client.full_name %><br>
<% end %>
something like this
<%= form_for(@staff) do |f| %>
<% if @staff.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@staff.errors.count, "error") %> prohibited this staff from being saved:</h2>
<ul>
<% @staff.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :full_name %><br>
<%= f.text_field :full_name %>
</div>
<div class="field">
<%= f.label :position %><br>
<%= f.text_field :position %>
</div>
<%= hidden_field_tag "staff[client_ids][]", nil %>
<% Client.all.each do |client| %>
<%= check_box_tag "staff[client_ids][]", client.id, @staff.client_ids.include?(client.id), id: dom_id(client) %>
<%= label_tag dom_id(client), client.full_name %><br>
<% end %>
<br>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
After this open
app/controllers/clients_controller.rb
app/controllers/staffs_controller.rb
in app/controllers/clients_controller.rb
add this code to your params
staff_ids: []
something like this
def client_params
params.require(:client).permit(:full_name, :business_name, staff_ids: [])
end
same with the staff controller but this time
client_ids: []
inside
def staff_params
params.require(:staff).permit(:full_name, :position, client_ids: [])
end
and thats it it should work for further explinations check this