【问题标题】:Rails 3 Nested Model Form, 2 levels deep using accepts_nested_attributes_forRails 3嵌套模型表单,使用accepts_nested_attributes_for深2层
【发布时间】:2011-08-21 10:26:11
【问题描述】:

我的嵌套模型表单在第一层深度上运行良好。但我的印象是,您可以使用 Accept_nested_attributes_for 深入许多层次。但是当我尝试下面的代码时,“图像”属性附加到顶级“问题”模型,它在表单提交时中断,出现未知属性“图像”错误。

我可以使用表单数据手动完成所有插入操作,但如果 R​​ails 可以自动处理它,那么显然会更好。

我做错了什么?我尝试改变 |af|在“:image do”的字段中为其自己的唯一名称,但它没有任何效果。

型号:

class Question < ActiveRecord::Base
  has_one :answer
  accepts_nested_attributes_for :answer
end

class Answer < ActiveRecord::Base
  belongs_to :question
  has_one :image
  accepts_nested_attributes_for :image
end

class Image < ActiveRecord::Base
  belongs_to :answer
end

控制器:

def new
    @question = Question.new
    answer = @question.build_answer
    image = answer.build_image

    @case_id = params[:id]

    render :layout => 'application', :template => '/questions/form' 
end

def create
  question_data = params[:question]
  @question = Question.new(question_data)
  if @question.save
  ...
end

查看:

= form_for @question, :html => {:multipart => true} do |f|

  = f.label :text, "Question Text:"
  = f.text_area :text, :rows => 7

  %br
  %br

  =f.fields_for :answer, do |af|
    = af.label :body, "Answer Text:"
    = af.text_area :body, :rows => 7

    %br
    %br

    = f.fields_for :image do |af|
      = af.label :title, "Image Title:"
      = af.text_field :title

      %br

      = af.label :file, "Image File:"
      = af.file_field :file

      %br

      = af.label :caption, "Image Caption:"
      = af.text_area :caption, :rows => 7

  = hidden_field_tag("case_id", value = @case_id)

  = f.submit

【问题讨论】:

    标签: forms ruby-on-rails-3


    【解决方案1】:

    我认为您将表单变量稍微混淆了。应该是:

    = form_for @question, :html => {:multipart => true} do |f|
    
      = f.label :text, "Question Text:"
      = f.text_area :text, :rows => 7
    
      %br
      %br
    
      =f.fields_for :answer, do |af|
        = af.label :body, "Answer Text:"
        = af.text_area :body, :rows => 7
    
        %br
        %br
    
        = af.fields_for :image do |img_form|
          = img_form.label :title, "Image Title:"
          = img_form.text_field :title
    
          %br
    
          = img_form.label :file, "Image File:"
          = img_form.file_field :file
    
          %br
    
          = img_form.label :caption, "Image Caption:"
          = img_form.text_area :caption, :rows => 7
    
      = hidden_field_tag("case_id", value = @case_id)
    
      = f.submit
    

    注意form_for ... do |f| 是如何产生f.fields_for ... do |af| 的,而af.fields_for ... do |img_form| 又是如何产生的。

    关键是第二个fields_for。它应该是af.fields_for :image do |img_form| 而不是f.fields_for :image do |img_form|

    【讨论】:

    • 谢谢,解决了这个问题。我现在唯一的问题是,当我提交表单时,我收到表单错误“答案不能为空白”。我猜这是因为“答案”有一个名为 question_id 的必填字段,似乎它可能没有被填写。有什么想法吗?
    • 没错。发生这种情况是因为父对象 (Question) 是一条新记录,因此当您尝试保存子对象 (Answer) 时它还不存在(即没有 id)。您可以删除对 question_id 或控制器的验证,首先保存父对象 (@question.save),然后保存子对象 (@question.answers &lt;&lt; @answer)。类似的东西......有关更多信息,请查看此article。 HTH
    • 真的想不通吗?在下面的 Railscast(尽管是 Rails 2.3)中,作者用一个简单的@survey.new/@survey.save 做了我想做的事情。 link 对他来说,Rails 只是想通了一切并正确地进行了关联。 Rails 3 真的不再处理这个问题了吗?这是他项目的 github 源代码:link 还是我在做一些不同的事情?
    • Rails 3 应该没有区别。我认为你所拥有的和 railscast 之间的区别在于你的 Answer 模型中有一个 validates_presence_of :question。尝试删除此验证。
    • 是的,这让我遇到了一个新错误,图像文件上传器需要 case_id。基本上归结为我必须拥有那个案例 ID,而且我还需要在某个时候拥有那个 answer_Id 才能动态地执行此操作,因此我将使其变得简单并手动完成并保留我的验证。非常感谢您的帮助!
    猜你喜欢
    • 2011-10-07
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多