我有两个模型:Book
和ReadingList
。一个ReadingList
has_and_belongs_to_many
Book
。在BooksController#show
页面上,我想要一个显示所有阅读列表的选择列表,并带有一个按钮,可将当前图书添加到选定的阅读列表中。
据推测,这应该转到ReadingListController#update
操作,但我不能将其指定为表单的URL,因为我不知道在创建表单时要向哪个ReadingList发送。我可以用JavaScript破解它,但我宁愿不依赖它。
在BooksController
中接受一个读取列表ID以添加图书的自定义操作会更好吗,或者我是否可以处理路由以便此请求最终转到ReadingListController#update
动作?
答案 0 :(得分:1)
显然,这可以通过使用Ajax提交表单轻松实现,但是在禁用/不可用JavaScript的情况下,最好的选择是在BooksController中添加自定义操作以将其添加到所需的读取列表。
你可以通过让表单指向BooksController中的动作来组合两者,但是有一个onsubmit处理程序通过Ajax发布到ReadingList控制器。
答案 1 :(得分:1)
我建议你有一个资源,它是一个ReadingListEntry,代表阅读列表中的一本书。然后你可以简单地POST到该资源来添加它。实际上并不需要成为它背后的模型,你可以直接操作阅读列表。
答案 2 :(得分:1)
我会创建一个自定义操作和路由,以便您可以提供book_id和list_id并形成关系。
假设你正在使用宁静的路线
resources :books do
post '/lists/:list_id/subscribe' => 'lists#subscribe', :as => :subscribe
end
def subscribe
@list = List.find params[:list_id]
@book = Book.find params[:book_id]
@list << @book
end
现在你可以使用带有或不带ajax的button_to。
答案 3 :(得分:1)
也许has_many :through
关系会更好?我喜欢Anthony关于ReadingListEntry资源的想法 - 或许放在后面的模型给你:
# models/book.rb
has_many :reading_list_entries
has_many :reading_lists, :through => :reading_list_entries
答案 4 :(得分:0)
我认为您在这里更改的是Book
,而不是ReadingList
。因此,您应该使用新的list_id
属性Puts到BooksController #newed资源。
# in views/books/show.html.erb
<%= form_for @book, :url => book_path(@book) do |f| =>
<%= f.select :list, ReadingList.all.map { |l| [l.name, l.id] } =>
<%= submit_tag "Change" =>
<% end %>
# in controllers/books_controller.rb
# params[:book][:list_id] => 123
def update
@book = Book.find(params[:id])
@book.update_attributes(params[:book])
end
# config/routes.rb
resources :books
resources :lists do
resources :books
end
如果您希望图书属于多个阅读列表,则需要has_and_belongs_to_many
关系