La mayoría de las veces, cuando necesitaba una identificación, puedo agruparla en una lista corta. Al crear asociaciones anidadas o la conexión de las asociaciones a través de. Supongamos que tenemos: :user
que tienen :pets
hasta :user_pets
asociación, donde guardaremos su tipo.
Si tenemos un bien configurado "has_many: a través de la Asociación" podemos simplemente User.pets.create(name: "Rex")
pero esto es demasiado simplista, ya que queremos para conformar :pet
tipo de :user_pets
.
u = User.create(name: "Cesar")
u.id # => 1 # works fine
p = u.pets.create(name: 'Rex')
# => rails will create UserPets => {id: 1, user_id: 1, pet_id: 1} for us
# But now we have a problem, how do we find :user_pets of our :pet?
# remember we still need to update the :type, the ugly (wrong) way:
up = p.user_pets.first
up.type = 'dog'
up.save! # working but wrong
# Do you see the problems here? We could use an id
P = Pet.new(name: "Destroyer")
p.id # will not work, as the pet not saved yet to receive an id
up = UserPet.new(user_id: U.id, pet_id: p.id)
# => UserPet {id: 2, user_id: 1, pet_id: nil} # as we expected there is no id.
# What solutions do we have? Use nested creation!
# Good
up = UserPet.new(user_id: u.id, type: "dog")
# even better
up = u.user_pets.new(type: "dog")
# it's just a shortcut for the code above,
# it will add :user_id for us, so let's just remember it.
# Now lets add another 'new' from our creatd 'user_pet'
p = up.pets.new(name: "Millan")
user.save!
# => UserPet: {id: 3, user_id: 1, pet_id: 2, type: 'dog'} # => Pet: {id: 2, name: "Sam"}
# everything is working! YEY!
# we can even better, than writing in the beginning "User.create",
# we can write "User.new" and save it with all the nested elements.
¿Viste cómo esto creó todos los identificadores para nosotros? ¡Pasemos a algo aún más complejo! Ahora tenemos una tabla adicional :shampoo
que exactamente como :user_pet
, pertenece a una :pet
y una :user
Necesitamos crear sin saber el id de la :user
y :pet
u = User.new('Mike')
up = u.user_pets.new(type: "cat")
p = up.pets.new(name: "Rowe")
# But what are we doing now?
# If we do:
s = u.shampoos.new(name: "Dirty Job")
# => Shampoo: {user_id: 2, pet_id: nil, name: "..."}
# We get "pet_id: nil", not what we want.
# Or if we do:
s = p.shampoos.new(name: "Schneewittchen")
# => Shampoo: {user_id: nil, pet_id: 3, name: "..."}
# We get "user_id: nil", in both cases we do not get what we want.
# So we need to get the id of not created record, again.
# For this we can just do as in the first example (order is not important)
s = u.shampoos.new(name: "Mission Impossible")
# => Shampoo: {id: 3, user_id: 2, pet_id: nil, name: "..."}
s.pet = p # this will give the missing id, to the shampoo on save.
# Finish with save of the object:
u.save! #=> Shampoo: {id: 3, user_id: 2, pet_id: 3, name: '...'} # => Pet: ...
# Done!
traté de cubrir causas más comunes a la hora necesitas identificación de elemento y cómo superar esto. Espero que sea útil.
Alguien con más conocimiento de Rails puede confirmar esto, pero generalmente la ID genera la ID así que no hay forma de saber qué es hasta que inserte la fila. Por supuesto, puede generar ID usted mismo, pero eso abre una lata de lombrices ... – roryf