1

我有 2 个模型,Category并且LineItemTypes

两者已经存在很多,现在需要将它们关联起来。每个类别都有许多 LineItemTypes。

我已经添加accepts_nested_attributes_for :line_item_typesCategory

我尝试hidden_field在表单上使用 a 来创建现有关联的列表LineItemTypes

- form_for @category do |form|
  %ul#categorised
    - form.fields_for :line_item_types do |line_item_types|
      -categorised.each do |l|
        %li
          =l.description
          =line_item_types.hidden_field :category_id

  =form.submit

如果我将一个项目添加到该列表中,我会收到错误消息,指出找不到该类别的 LineItemType。我认为如果该关联不存在,accepts_nested_attributes_for 会添加该关联。还是仅用于“创建”新记录和修改现有关系,而不是创建新关系。

a.update_attributes({:line_item_types_attributes => [{:id => 2767}, {:id => LineItemType.find(2).id}]})
ActiveRecord::RecordNotFound: Couldn't find LineItemType with ID=2 for Category with ID=1

任何想法都无需编写任何东西来遍历生成的表单参数并创建关联?或者更简单的方法来实现这一点?

4

3 回答 3

2

我得出的结论是,accepts_nested_attributes_for 的工作方式有点像 url_for ... ID 的存在使它假设关系存在。渲染 accept_nested_attributes_for 不适合我想做的事情。

我已经使用前置过滤器解决了这个问题:

def find_line_item_types
  params[:category][:line_item_types] = LineItemType.find(params[:category][:line_item_types].collect { |a| a[0].to_i }) if params[:category] and params[:category][:line_item_types]
end
于 2010-11-03T14:12:48.157 回答
0

好吧,我遇到了同样的问题,所以我搜索了源代码并修补了猴子accepts_nested_attributes_for以允许这种行为......

https://gist.github.com/2223565

看起来很多,但实际上我只是修改了几行:

module ActiveRecord::NestedAttributes::ClassMethods
  def accepts_nested_attributes_for(*attr_names)
    # ...
    #options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only)
    options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only, :allow_existing)
    # ...
  end
end

和...

module ActiveRecord::NestedAttributes
  def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {})
    # ...
    #existing_records = if association.loaded?
    #  association.target
    #else
    #  attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
    #  attribute_ids.empty? ? [] : association.scoped.where(association.klass.primary_key => attribute_ids)
    #end

    existing_records = if options[:allow_existing] or not association.loaded?
      attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
      scope = options[:allow_existing] ? association.target_scope : association.scoped
      scope.where(association.klass.primary_key => attribute_ids)
    else
      association.target
    end
    # ...
  end
end
于 2012-03-28T04:20:57.430 回答
0

不,您应该能够从 Category 实例创建 line_item_types 而无需在 line_item_types 属性中指定 category_id !

你应该检查你的 has_many 和 belongs_to 声明中是否有 :inverse_of 选项。

# in Category
has_many :line_item_types, :inverse_of => :category

# In LineItemType
belongs_to :category, :inverse_of => :line_item_types

告诉我这是否有帮助。

于 2010-11-02T14:46:09.450 回答