嵌套 Rails 模型 - 创建时忽略 child_index

Posted

技术标签:

【中文标题】嵌套 Rails 模型 - 创建时忽略 child_index【英文标题】:Nested Rails models - ignoring child_index on create 【发布时间】:2011-10-28 13:37:26 【问题描述】:

所以,我一直在使用代码在嵌套模型 Railscast 中添加新模型。无论出于何种原因,添加新字段的代码中的 fields_for 似乎忽略了 child_index 参数。这让我非常抓狂,因为我在其他地方使用了不同模型的相同代码,并且运行良好。

型号:

#models/gradebook_settings.rb
class GradebookSettings
include Mongoid::Document

  has_many :assignment_types
  accepts_nested_attributes_for :assignment_types, :allow_destroy => true
  field :weight_type, :type => String, :default => "equal_weight"

end

#models/assignment_type.rb
class AssignmentType
include Mongoid::Document

  has_many :assignments
  belongs_to :gradebook_settings, :class_name => "GradebookSettings"

  field :course_id, :type => Integer
  field :name, :type => String
  field :weight, :type => Integer
end

查看和部分:

#views/gradebook_settings/new.html.haml
=form_for @settings, :remote => true, :url => "/settings/#@settings.id/weight", :html => :method => "put" do |f|
  %div:id => "assignment_types", :style => ""
    =f.fields_for :assignment_types do |builder|
      =render "assignment_type_fields", :f => builder
  %div:id => "weight_type"
   %div:id => "equal_weight"
      =f.label :weight_type, "Equal Weight"
      =f.radio_button :weight_type, :equal_weight
    %div:id => "no_weight"
      =f.label :weight_type, "No Weight"
      =f.radio_button :weight_type, :no_weight
    %div:id => "manual_weight"
      =f.label :weight_type, "Manual Weight"
      =f.radio_button :weight_type, :manual_weight
    =link_to_add_fields "+ Add Type", f, :assignment_types
  %button:type => "button", :class => "button", :id => "submit_weight"="Submit"
  =close_openBox_button


#views/gradebook_settings/_assignment_type_fields.html.haml
%div:class => "assignment_type"
  =f.text_field :name, :size => "30"
  =f.text_field :weight, :size => "3", :maxlength => "2", :float => "right"
  =f.hidden_field :_destroy, :class => "type_destroy_field"
  %span:class => "remove_button button"=button_to_function "X", "remove_fields(this, 'assignment_type')"

#helpers/application_helper.rb
def link_to_add_fields(name, f, association)
  new_object = f.object.class.reflect_on_association(association).klass.new
  fields = f.fields_for(association, new_object, :child_index => "new_#association") do |builder|
    render(association.to_s.singularize + "_fields", :f => builder)
  end
  button_to_function(name, "add_fields(this, '#association', '#escape_javascript(fields)')", :id => "add_range_button")
end

Javascript:

function add_fields(link, association, content) 
  var new_id = new Date().getTime();
  var regexp = new RegExp("new_" + association, "g");
  var html = content.replace(regexp, new_id);
  $(link).parent().prev().append(html);

当我创建新模型时,我得到了所有正确的字段,但它们缺少子索引 - 它不是空的 ([]),它只是不存在。关于为什么会发生这种情况的任何想法?它与我的其他嵌套模型完美配合,当我在常规 fields_for 中使用 child_index 时,它似乎工作正常。

谢谢!

【问题讨论】:

我认为问题可能出在您的控制器代码中。你的孩子指数到底是什么?在您列出的任何一个模型中,我都没有看到任何索引字段。你是说身份证吗? 我可能误解了 link_to_add_fields 代码的工作原理,但那是我所指的子索引。 Rails 3 似乎正在为未动态创建的嵌套表单元素自动插入子索引 - 也就是说,第一个插入字段之一的 name 属性是 "gradebook_settings[assignment_types_attributes][0][name]" 其中 0是 child_index。 我看到了同样的行为,它只出现在新/创建操作上,而不是编辑/更新操作。表单字段中缺少子索引。 它在 mysql 中,我面前没有它,但我似乎记得必须在我设置 accept_nested_attributes 的关系上设置 attr_accessible。 你知道你可以只写 "#manual_weight" 而不是 "%div:id => "manual_weight"" - 阅读该视图代码会产生很多噪音,(并为您节省大量打字时间)。 【参考方案1】:

检查您的 DOM 在您的 javascript 中遍历。

在我的用例中,我有以下脚本:

$(this).before($(this).data('fields').replace(regexp, time))

而不是

$(link).parent().prev().append(html);

实现与您的目标相似的结果。

我认为通过调用 .prev 选择器,您将跳转到前一个 div,并且我认为这对于您想要实现的目标来说在 DOM 树上移动得太远了。

【讨论】:

以上是关于嵌套 Rails 模型 - 创建时忽略 child_index的主要内容,如果未能解决你的问题,请参考以下文章

我的 rails 嵌套模型无法识别 _destroy 属性

在rails 2.3+中测试(rspec)嵌套模型部分

- 更新 - Rails API 应用程序使用来自控制器的 POST 请求一次创建不同模型的多个嵌套记录

Rails:不使用参数时关联两个不同的模型[:id]

Rails视图中的嵌套模型

具有多个嵌套模型的 Rails 表单会导致无线电组出现问题