Rails 4:在创建模型时能够 select 一个模型的多个实例,它具有 has_many :through 关系
Rails 4: Being able to select multiple instances of one model when creating the model it has a has_many :through relationship with
当我向我的 Library
添加新的 Book
时,我希望能够指定 Shelves
(注意: " Shelf
" 是我在我的应用程序中用于将 Books
分组在 Library
中的模型的术语;该模型的更好名称应该是 Category
或 Genre
,但我很笨)在那个 Library
它应该属于。现在,我可以将 Book
添加到我的 Library
,但我遇到了 Shelves
的问题。我在学习方面还很陌生 Rails,如果有任何帮助,我将不胜感激。
型号
user.rb:
class User < ActiveRecord::Base
has_one :library, dependent: :destroy
...
end
library.rb:
class Library < ActiveRecord::Base
belongs_to :user
has_many :shelves, dependent: :destroy
has_many :catalogs, dependent: :destroy
has_many :books, :through => :catalogs, dependent: :destroy
...
end
book.rb:
class Book < ActiveRecord::Base
has_many :catalogs, dependent: :destroy
has_many :libraries, :through => :catalogs, dependent: :destroy
has_many :bookshelves, dependent: :destroy
has_many :shelves, :through => :bookshelves, dependent: :destroy
...
end
catalog.rb:
class Catalog < ActiveRecord::Base
belongs_to :book
belongs_to :library
end
shelf.rb:
class Shelf < ActiveRecord::Base
belongs_to :library
has_many :bookshelves, dependent: :destroy
has_many :books, :through => :bookshelves, dependent: :destroy
...
end
本书shelf.rb
class Bookshelf < ActiveRecord::Base
belongs_to :book
belongs_to :shelf
end
控制器
books_controller.rb
class BooksController < ApplicationController
...
def create
@book = Book.new(book_params)
@library = current_user.library
if @book.save
@book.catalogs.create(:library_id => @library.id)
flash[:success] = "Book added to library!"
redirect_to current_user
else
render 'current_user'
end
end
...
private
def book_params
params.require(:book).permit(:title, :author, :publisher, :isbn)
end
...
end
查看
_book_form.html.erb:
<%= form_for(@book) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_field :title, placeholder: "Book Title" %>
<%= f.text_field :author, placeholder: "Author" %>
<%= f.text_field :publisher, placeholder: "Publisher" %>
<%= f.text_field :isbn, placeholder: "ISBN" %>
<%= f.fields_for :catalogs do |ff| %>
<%= ff.hidden_field :library_id %>
<% end %>
<%= f.fields_for :bookshelves do |ff| %>
<%= ff.collection_select :shelf_ids, current_user.library.shelves.all.collect {|x| [x.name, x.id]}, {}, multiple: true %>
<% end %>
</div>
<%= f.submit "Add Book to Library", class: "btn btn-primary" %>
<% end %>
在您的 book_params
方法中,您没有列出 shelf_ids
。所以它不会被传递到 .new
方法,因此它不会被保存。因为你不想多个 ids
,所以你想这样做:
def book_params
params.require(:book).permit(:title, :author, :publisher, :isbn, shelf_ids: [])
end
这样,控制器就知道它是一个数组,而不仅仅是一个值。
哦,顺便说一句,shelf_ids
和任何其他类似的数组值 必须 放在末尾,否则会引发错误。
编辑:
同时更改这部分代码:
<%= f.fields_for :bookshelves do |ff| %>
<%= ff.collection_select :shelf_ids, current_user.library.shelves.all.collect {|x| [x.name, x.id]}, {}, multiple: true %>
<% end %>
对此:
<%= f.collection_select :shelf_ids, current_user.library.shelves.all.collect {|x| [x.name, x.id]}, {}, multiple: true %>
您无需担心关联的 through
部分。只需设置 has_many
部分即可。
当我向我的 Library
添加新的 Book
时,我希望能够指定 Shelves
(注意: " Shelf
" 是我在我的应用程序中用于将 Books
分组在 Library
中的模型的术语;该模型的更好名称应该是 Category
或 Genre
,但我很笨)在那个 Library
它应该属于。现在,我可以将 Book
添加到我的 Library
,但我遇到了 Shelves
的问题。我在学习方面还很陌生 Rails,如果有任何帮助,我将不胜感激。
型号
user.rb:
class User < ActiveRecord::Base
has_one :library, dependent: :destroy
...
end
library.rb:
class Library < ActiveRecord::Base
belongs_to :user
has_many :shelves, dependent: :destroy
has_many :catalogs, dependent: :destroy
has_many :books, :through => :catalogs, dependent: :destroy
...
end
book.rb:
class Book < ActiveRecord::Base
has_many :catalogs, dependent: :destroy
has_many :libraries, :through => :catalogs, dependent: :destroy
has_many :bookshelves, dependent: :destroy
has_many :shelves, :through => :bookshelves, dependent: :destroy
...
end
catalog.rb:
class Catalog < ActiveRecord::Base
belongs_to :book
belongs_to :library
end
shelf.rb:
class Shelf < ActiveRecord::Base
belongs_to :library
has_many :bookshelves, dependent: :destroy
has_many :books, :through => :bookshelves, dependent: :destroy
...
end
本书shelf.rb
class Bookshelf < ActiveRecord::Base
belongs_to :book
belongs_to :shelf
end
控制器
books_controller.rb
class BooksController < ApplicationController
...
def create
@book = Book.new(book_params)
@library = current_user.library
if @book.save
@book.catalogs.create(:library_id => @library.id)
flash[:success] = "Book added to library!"
redirect_to current_user
else
render 'current_user'
end
end
...
private
def book_params
params.require(:book).permit(:title, :author, :publisher, :isbn)
end
...
end
查看
_book_form.html.erb:
<%= form_for(@book) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_field :title, placeholder: "Book Title" %>
<%= f.text_field :author, placeholder: "Author" %>
<%= f.text_field :publisher, placeholder: "Publisher" %>
<%= f.text_field :isbn, placeholder: "ISBN" %>
<%= f.fields_for :catalogs do |ff| %>
<%= ff.hidden_field :library_id %>
<% end %>
<%= f.fields_for :bookshelves do |ff| %>
<%= ff.collection_select :shelf_ids, current_user.library.shelves.all.collect {|x| [x.name, x.id]}, {}, multiple: true %>
<% end %>
</div>
<%= f.submit "Add Book to Library", class: "btn btn-primary" %>
<% end %>
在您的 book_params
方法中,您没有列出 shelf_ids
。所以它不会被传递到 .new
方法,因此它不会被保存。因为你不想多个 ids
,所以你想这样做:
def book_params
params.require(:book).permit(:title, :author, :publisher, :isbn, shelf_ids: [])
end
这样,控制器就知道它是一个数组,而不仅仅是一个值。
哦,顺便说一句,shelf_ids
和任何其他类似的数组值 必须 放在末尾,否则会引发错误。
编辑:
同时更改这部分代码:
<%= f.fields_for :bookshelves do |ff| %>
<%= ff.collection_select :shelf_ids, current_user.library.shelves.all.collect {|x| [x.name, x.id]}, {}, multiple: true %>
<% end %>
对此:
<%= f.collection_select :shelf_ids, current_user.library.shelves.all.collect {|x| [x.name, x.id]}, {}, multiple: true %>
您无需担心关联的 through
部分。只需设置 has_many
部分即可。