Creación y eliminación de asociaciones con accepts_nested_attributes_for
-
28-09-2019 - |
Pregunta
Tengo 2 modelos, Category
y LineItemTypes
Ya hay un montón existentes tanto, ahora es un requisito para que puedan estar asociados. Siendo muchos LineItemTypes para cada categoría.
He añadido accepts_nested_attributes_for :line_item_types
en Category
He intentado usar un hidden_field
en un formulario para crear una lista de LineItemTypes
existente asociada:
- 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
Si agrego un elemento a la lista, tengo errores diciendo que un LineItemType para esa categoría no se puede encontrar. Pensé accepts_nested_attributes_for añadiría la asociación si no existe. ¿O es sólo para 'crear' nuevos registros y la modificación de las relaciones existentes, no crear nuevas relaciones.
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
Todas las ideas sin tener que escribir algo para atravesar los parametros forma resultante y crear las asociaciones? O una forma aún más fácil de lograr esto?
Solución
he llegado a la conclusión de que las obras accepts_nested_attributes_for un poco como url_for ... Cuando la presencia de Identificación hace que asume la relación existe. Rendering accepts_nested_attributes_for no es adecuado para lo que yo quiero hacer.
He trabajado alrededor de este con un filtro antes:
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
Otros consejos
no debe ser capaz de crear una instancia de line_item_types Categoría sin especificar el category_id en los atributos line_item_types!
Se debe comprobar que tienes el:. Inverse_of opción en su has_many y belongs_to declaraciones
# in Category
has_many :line_item_types, :inverse_of => :category
# In LineItemType
belongs_to :category, :inverse_of => :line_item_types
Dime si eso ayuda.
Bueno, yo tenía el mismo problema, así que busqué en la fuente y el mono parcheado accepts_nested_attributes_for
para permitir este comportamiento ...
https://gist.github.com/2223565
Parece mucho, pero en realidad sólo modificada unas líneas:
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
Y ...
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