through references rails many has_one has_many has_and_belongs_to_many has example belongs and ruby-on-rails ruby-on-rails-3 associations

ruby on rails - references - Build vs new en Rails 3



rails references (5)

En los docs Rails 3, el método de build para asociaciones se describe como el mismo que el new , pero con la asignación automática de la clave externa. Directamente de los documentos:

Firm#clients.build (similar to Client.new("firm_id" => id))

He leído algo similar en otro lugar.

Sin embargo, cuando uso new (ej. some_firm.clients.new sin ningún parámetro), la asociación firm_id del nuevo cliente se crea automáticamente. ¡Estoy mirando los resultados ahora mismo en la consola!

¿Me estoy perdiendo de algo? ¿Los documentos están un poco desactualizados (poco probable)? ¿Cuál es la diferencia entre build y new ?


Model.new

Tag.new post_id: 1 creará una instancia de una etiqueta con su conjunto de post_id .

@ model.models.new

@post.tags.build hace lo mismo Y la etiqueta instanciada estará en @post.tags incluso antes de que se guarde.

Esto significa que @post.save guardará tanto el poste como la etiqueta recién construida (suponiendo que se haya configurado el valor inverso). Esto es genial porque Rails validará ambos objetos antes de guardarlos, y ninguno se guardará si alguno de ellos falla la validación.

models.new vs models.build

@post.tags.build y @post.tags.new son equivalentes (al menos desde Rails 3.2).


Estás malinterpretando los documentos un poco. some_firm.client.new está creando un nuevo objeto Client partir de la colección de clientes, por lo que puede establecer automáticamente el firm_id en some_firm.id , mientras que los documentos llaman a Client.new que no tiene ningún conocimiento del id. de ninguna empresa, por lo que necesita el firm_id pasado a él.

La única diferencia entre some_firm.clients.new y some_firm.clients.build parece ser que build también agrega el cliente recién creado a la colección de clients :

henrym:~/testapp$ rails c Loading development environment (Rails 3.0.4) r:001 > (some_firm = Firm.new).save # Create and save a new Firm #=> true r:002 > some_firm.clients # No clients yet #=> [] r:003 > some_firm.clients.new # Create a new client #=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> r:004 > some_firm.clients # Still no clients #=> [] r:005 > some_firm.clients.build # Create a new client with build #=> #<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil> r:006 > some_firm.clients # New client is added to clients #=> [#<Client id: nil, firm_id: 1, created_at: nil, updated_at: nil>] r:007 > some_firm.save #=> true r:008 > some_firm.clients # Saving firm also saves the attached client #=> [#<Client id: 1, firm_id: 1, created_at: "2011-02-11 00:18:47", updated_at: "2011-02-11 00:18:47">]

Si está creando un objeto a través de una asociación, debe preferir la compilación a la new ya que build mantiene su objeto en memoria, some_firm (en este caso) en un estado consistente incluso antes de que cualquier objeto se haya guardado en la base de datos.


Tiene razón, la compilación y las nuevas funciones tienen el mismo efecto de establecer la clave externa, cuando se llaman a través de una asociación. Creo que la razón por la cual la documentación está escrita así es para aclarar que se está creando una instancia de un nuevo objeto Cliente, a diferencia de una nueva relación de registro activo. Este es el mismo efecto que llamar .new en una clase tendría en Ruby. Es decir que la documentación está aclarando que invocar construir sobre una asociación es lo mismo que crear un nuevo objeto (llamar .new) y pasar las claves externas a ese objeto. Estos comandos son todos equivalentes:

Firm.first.clients.build Firm.first.clients.new Client.new(:firm_id => Firm.first.id)

Creo que la razón por la que .build existe es que Firm.first.clients.new podría interpretarse en el sentido de que está creando un nuevo objeto de relación has_many, en lugar de un cliente real, por lo que llamar a .build es una forma de aclarar esto.


construir vs nuevo:

la mayoría de las veces nuevas y compiladas son las mismas, pero las compilaciones almacenan objetos en la memoria,

p.ej.

para nuevo:

Client.new(:firm_id=>Firm.first.id)

Para la construcción:

Firm.first.clients.build

Aquí los clientes se almacenan en la memoria, cuando se guardan firmes, también se guardan los registros asociados.