我正在尝试创建一个嵌套的属性表单来创建一个模型,该模型主要是两个其他模型之间的关联“连接器”。就我而言,模型代表books
,awards
和“连接器”模型book_awards
。当我正在编辑一本书时,我希望能够快速选择它赢得的奖项。
我一直在用 http://railscasts.com/episodes/196-nested-model-form-part-1 帮助我开始,但我担心我几乎被卡住了。
另一个看似相似的问题是 accepts_nested_attributes_for with find_or_create?不幸的是,这也不是我正在做的事情,而且我无法适应它。
我的模特看起来像这样。每个模型都有其他属性和验证等,但为了清楚起见,我删除了它们。
class Book < ActiveRecord::Base
has_many :book_awards
accepts_nested_attributes_for :book_awards, :allow_destroy => true
end
class Award < ActiveRecord::Base
has_many :book_awards
end
class BookAward < ActiveRecord::Base
belongs_to :book, :award
end
在我的书籍控制器编辑方法和新方法,以及创建和更新的失败案例中,我有一行@awards = Award.all
。
在我看来,我希望看到所有奖项的清单,旁边有复选框。当我提交时,我想更新,创建或销毁 book_award
模型。如果选中该复选框,我想更新现有模型或创建一个新模型(如果它不存在)。如果未选中该复选框,那么我想销毁现有模型,或者如果该奖项从未存在则不执行任何操作。我有book_awards
的部分内容。我不确定复选框选择器是否应该在此部分中。
我认为我的复选框将成为:_destroy
的钩子,但其极性反转。我认为这样的事情基本上会这样做:
= f.check_box :_destroy, {}, 0, 1
目前,我有部分内容,但我不确定它到底在哪里。
接下来我的观点目前无效,但也许有助于展示我正在尝试做的事情。我遍历awards
并使用fields_for
为已存在的任何内容设置嵌套属性。它非常丑陋,但我认为它有点奏效。但是,我真的不知道如何开始使用else案例。
= f.label :awards
- @awards.each do |a|
- if f.object.awards && f.object.awards.include?(a)
= f.fields_for :book_awards, f.object.book_award.select{|bas| bas.award == a } do |ba|
= render 'book_awards', :f => ba, :a => a
- else
= fields_for :book_awards do |ba|
= render 'book_awards', :f => ba, :a => a
我希望奖项每次都以相同的顺序列出(控制器中的@awards
作业可能会指定订单),而不是首先列出现有奖励。
答案 0 :(得分:0)
我不想回答我自己的问题,但我终于找到了可行的方法。我需要做的第一件事是根据railscast中包含的疯狂对象更新“新”案例。接下来,我需要手动设置:child_index
。最后,我需要适当地手动设置:_destroy
复选框。
.field
= f.label :awards
- @awards.each_with_index do |a,i|
- if exists = (f.object.awards && f.object.awards.include?(a))
- new_ba = f.object.book_awards.select{|s| s.award == a}
- else
- new_ba = f.object.class.reflect_on_association(:book_awards).klass.new
= f.fields_for :book_awards, new_ba, :child_index => i do |ba|
= render 'book_awards', :f => ba, :a => a, :existing => exists
我的部分看起来像这样:
.field
= f.check_box :_destroy, {:checked => existing}, 0, 1
= f.label a.name
= f.hidden_field :award_id, :value => a.id
= f.label :year
= f.number_field :year
它并不是非常漂亮,但它似乎正是我想要的。