2012-07-23 20 views
10

que tienen un par de clases:: autoguardado ignorado en la relación has_many - ¿Qué me falta?

class Collection < ActiveRecord::Base                                                   
    has_many :items, autosave: true 
end 

class Item < ActiveRecord::Base 
    belongs_to :collection 
end 

Desde el docs:

Cuando: copia de seguridad automática es cierto que todos los niños se guarda, no importa si son registros nuevos:

Pero cuando actualizo un Item y guardo su padre Collection, los atributos upated de Item no se guardan:

> c = Collection.first 
=> #<Collection id: 1, name: "collection", created_at: "2012-07-23 00:00:10", updated_at: "2012-07-23 00:00:10"> 
> i = c.items.first 
=> #<Item id: 1, collection_id: 1, name: "item1", created_at: "2012-07-23 00:00:25", updated_at: "2012-07-23 00:00:25"> 
> i.name = 'new name' 
=> "new name" 
> c.save 
=> true 
> Collection.first.items 
=> [#<Item id: 1, collection_id: 1, name: "item1", created_at: "2012-07-23 00:00:25", updated_at: "2012-07-23 00:00:25">] 

Entonces, ¿qué es lo que me falta?

Estoy usando Rails 3.2.5 y Ruby 1.9.2.


Así que he hecho algunas investigaciones sobre el origen de ActiveRecord. Podemos conseguir el asimiento de Asociaciones del autoguardado c 's:

> c.class.reflect_on_all_autosave_associations 
=> [#<ActiveRecord::Reflection::AssociationReflection:0x007fece57b3bd8 @macro=:has_many, @name=:items, @options={:autosave=>true, :extend=>[]}, @active_record=Collection(id: integer, name: string, created_at: datetime, updated_at: datetime), @plural_name="items", @collection=true, @class_name="Item", @klass=Item(id: integer, collection_id: integer, name: string, created_at: datetime, updated_at: datetime), @foreign_key="collection_id", @active_record_primary_key="id", @type=nil>] 

Creo que esto ilustra que la asociación se ha establecido para el guardado automático.

Entonces podemos obtener la instancia de la asociación correspondiente a c:

> a = c.send :association_instance_get, :items 
=> #<ActiveRecord::Associations::HasManyAssociation:0x007fece738e920 @target=[#<Item id: 1, collection_id: 1, name: "item1", created_at: "2012-07-23 00:00:25", updated_at: "2012-07-23 00:00:25">], @reflection=#<ActiveRecord::Reflection::AssociationReflection:0x007fece57b3bd8 @macro=:has_many, @name=:items, @options={:autosave=>true, :extend=>[]}, @active_record=Collection(id: integer, name: string, created_at: datetime, updated_at: datetime), @plural_name="items", @collection=true, @class_name="Item", @klass=Item(id: integer, collection_id: integer, name: string, created_at: datetime, updated_at: datetime), @foreign_key="collection_id", @active_record_primary_key="id", @type=nil>, @owner=#<Collection id: 1, name: "collection", created_at: "2012-07-23 00:00:10", updated_at: "2012-07-23 00:00:10">, @updated=false, @loaded=true, @association_scope=[#<Item id: 1, collection_id: 1, name: "item1", created_at: "2012-07-23 00:00:25", updated_at: "2012-07-23 00:00:25">], @proxy=[#<Item id: 1, collection_id: 1, name: "item1", created_at: "2012-07-23 00:00:25", updated_at: "2012-07-23 00:00:25">], @stale_state=nil> 

Entonces podemos encontrar los objetos reales que están asociados a través de esta asociación:

> a.target 
=> [#<Item id: 1, collection_id: 1, name: "item1", created_at: "2012-07-23 00:00:25", updated_at: "2012-07-23 00:00:25">] 

El objeto encontrar aquí hace no tengo la actualización que había hecho antes.

Respuesta

13

El problema aquí es la línea

i = c.items.first 

Esta línea de tira del elemento correcto de la base de datos, pero no adjuntarlo a la colección c. Es un objeto de rubí distinto del objeto

i = c.items[0] 

Si reemplaza la primera línea con la segunda, funcionará su ejemplo.

+1

Gracias. Y aquí pensé .primero == [0] – Arcolye

+1

Normalmente, básicamente lo es. Esta diferencia se debe a que Rails convierte útilmente #primero en predicados de SQL. Puede ver la fuente C de Ruby # first aquí: http://ruby-doc.org/core-2.1.3/Enumerable.html#method-i-first y la relación de Ralis aquí: https://github.com/rails/ rails/blob/f244d8f53279efd755e7299418b408641baedc9c/activerecord/lib/active_record/relation/finder_methods.rb # L128 – bronson

Cuestiones relacionadas