web-dev-qa-db-fra.com

comment ajouter des enregistrements à has_many: via l'association dans rails

class Agents << ActiveRecord::Base
  belongs_to :customer
  belongs_to :house
end

class Customer << ActiveRecord::Base
  has_many :agents
  has_many :houses, through: :agents
end

class House << ActiveRecord::Base
  has_many :agents
  has_many :customers, through: :agents
end

Comment puis-je ajouter au modèle Agents pour Customer?

Est-ce le meilleur moyen?

Customer.find(1).agents.create(customer_id: 1, house_id: 1)

Ce qui précède fonctionne bien depuis la console, cependant, je ne sais pas comment y parvenir dans l’application réelle.

Imaginez un formulaire pour le client qui prend également house_id comme entrée. Puis-je effectuer les opérations suivantes dans mon contrôleur?

def create 
  @customer = Customer.new(params[:customer])
  @customer.agents.create(customer_id: @customer.id, house_id: params[:house_id])
  @customer.save
end

Globalement, je suis confus quant à la façon d'ajouter des enregistrements dans le has_many :through table?

89
Mike

Je pense que vous pouvez simplement faire ceci:

 @cust = Customer.new(params[:customer])
 @cust.houses << House.find(params[:house_id])

Ou lors de la création d'une nouvelle maison pour un client:

 @cust = Customer.new(params[:customer])
 @cust.houses.create(params[:house])

Vous pouvez également ajouter via les identifiants:

@cust.house_ids << House.find(params[:house_id])
147
Mischa

Le "meilleur moyen" dépend de vos besoins et de ce qui vous semble le plus confortable. La confusion provient des différences de comportement d'ActiveRecord entre les méthodes new et create et le << _ opérateur.

La méthode new

new n'ajoutera pas d'enregistrement d'association pour vous. Vous devez créer les enregistrements House et Agent:

house = @cust.houses.new(params[:house])
house.save
agent = Agent(customer_id: @cust.id, house_id: house.id)
agent.save

Notez que @cust.houses.new et House.new sont en fait les mêmes car vous devez créer l’enregistrement Agent dans les deux cas.

Le << Opérateur

Comme le mentionne Mischa, vous pouvez également utiliser le << opérateur sur la collection. Ceci construira seulement le modèle Agent pour vous, vous devez construire le modèle House:

house = House.create(params[:house])
@cust.houses << house
agent = @cust.houses.find(house.id)

La méthode create

create construira les enregistrements House et Agent pour vous, mais vous devrez trouver le modèle Agent si vous souhaitez le renvoyer à votre vue ou api:

house = @cust.houses.create(params[:house])
agent = @cust.agents.where(house: house.id).first

Pour terminer, si vous souhaitez que des exceptions soient générées lors de la création de house, utilisez plutôt les opérateurs bang (par exemple, new! et create!).

72
IAmNaN

Une autre façon d’ajouter des associations consiste à utiliser les colonnes de clé étrangère:

agent = Agent.new(...)
agent.house = House.find(...)
agent.customer = Customer.find(...)
agent.save

Ou utilisez les noms de colonne exacts en passant l'ID de l'enregistrement associé à la place de l'enregistrement.

agent.house_id = house.id
agent.customer_id = customer.id
5
Dennis