comment append des enregistrements à has_many: par association en 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 append au modèle Agents pour le Customer ?

Est-ce la meilleure façon?

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

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

Imaginez qu’un formulaire soit rempli pour le client qui prend également house_id en 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 

Dans l’ensemble, je ne comprends pas comment append des enregistrements dans la table has_many :through ?

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 append des identifiants via:

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

«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 avec les méthodes new et create et avec l’opérateur < < .

La new méthode

new n’appenda pas de fiche d’association pour vous. Vous devez construire la House et l' Agent enregistre vous-même:

 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 effectivement les mêmes, car vous devez créer l'enregistrement de l' Agent dans les deux cas.

Le < < opérateur

Comme Mischa le mentionne, vous pouvez également utiliser l'opérateur < < sur la collection. Cela ne fera que construire le modèle d' Agent pour vous, vous devez créer le modèle House :

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

La méthode de create

create va créer à la fois les enregistrements House et Agent , mais vous devrez trouver le modèle Agent si vous souhaitez le renvoyer à votre vue ou à votre API:

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

Pour finir, si vous voulez que les exceptions soient déclenchées lors de la création de house utilisez plutôt les opérateurs bang (par exemple new! Et create! ).

Une autre façon d’append 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 transmettant l’ID de l’enregistrement associé au lieu de l’enregistrement.

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