Skip to content

Instantly share code, notes, and snippets.

@Mikke
Created March 13, 2012 20:35
Show Gist options
  • Save Mikke/2031392 to your computer and use it in GitHub Desktop.
Save Mikke/2031392 to your computer and use it in GitHub Desktop.
Rails 3 has_many use checkboxes and multiple select in the form
rails g scaffold Book title:string description:text
rails g scaffold Pubhouse title:string address:text
rails g model BookPubhouse book_id:integer pubhouse_id:integer
rake db:migrate
# 'app/models/book.rb'
class Book < ActiveRecord::Base
has_many :book_pubhouses, :dependent => :destroy # уничтожать вместе с основным экземпляром
has_many :pubhouses, :through => :book_pubhouses # through указывает Rails приложению зависимость двух моделей через третью, теперь мы можем использовать Book.pubhouses напрямую
# валидация
validates :title, :presence => true
validates :title, :uniqueness => true
validates :title, :length => { :maximum => 150 }
validates :description, :length => { :maximum => 2000 }
end
# 'app/models/pubhouse.rb'
class Pubhouse < ActiveRecord::Base
has_many :book_pubhouses, :dependent => :destroy
has_many :shops, :through => :book_pubhouses
validates :title, :presence => true
validates :title, :uniqueness => true
validates :title, :length => { :maximum => 150 }
validates :address, :length => { :maximum => 2000 }
end
# 'app/models/book_pubhouse.rb'
class BookPubhouse < ActiveRecord::Base
belongs_to :book
belongs_to :pubhouse
validates :book_id, :presence => true
validates :pubhouse_id, :presence => true
validates :pubhouse_id, :uniqueness => {:scope => :book_id}
end
<%= form_for(@book) do |f| %>
...
<div class="param">
<%= f.label :pubhouses %>
<span class="ul">
<% Pubhouse.all.each do |pubhouse| %>
<label class="li"><%= check_box_tag :pubhouse_ids, pubhouse.id, @book.pubhouses.include?(pubhouse), :name => 'book[pubhouse_ids][]' %> <u><%= pubhouse.title %></u></label><br />
<% end %>
</span>
</div>
...
<% end %>
<%= form_for(@book) do |f| %>
...
<div class="param">
<%= f.label :pubhouses %>
<%= select_tag("book[pubhouse_ids][]", options_for_select(Pubhouse.all.collect { |pubhouse| [pubhouse.title, pubhouse.id] }, @book.pubhouses.collect { |pubhouse| pubhouse.id}), {:multiple=>true, :size=>5}) %>
</div>
...
<% end %>
@Mikke
Copy link
Author

Mikke commented Mar 13, 2012

@embs
Copy link

embs commented Feb 19, 2013

This helped me a lot! Thanks!

@abhishekcol
Copy link

Thank you for this explanation. I tried this, but im finding it difficult to save the selected values in MySQL db. Can you please let me know how to solve this issue such that i can display the selected values in the index view.

@agustinmar
Copy link

i want know about the controller for edit and delete

@rmetel
Copy link

rmetel commented May 7, 2015

Could you please post your controller? Thanks. ;)

@kennycyb
Copy link

Use accepts_nested_attributres_for in model, see http://stackoverflow.com/questions/17585215/how-to-update-attributes-in-many-to-many-relation-in-rails

For rails 4, in the controller:

def create
...
    if @book.save
      @book.pubhouses.build
...
end

def update
...
  if @book.save
    @book.pubhouses.build
...
end

def book_params
  params.require(:book).permit(pubhouse_ids: [])
end

@Jackiesan
Copy link

This is very helpful thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment