добавление записей имеет много:через ассоциации в 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

как мне добавить к Agents модель Customer?

это лучший способ?

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

вышеизложенное отлично работает с консоли, однако я не знаю, как добиться этого в реальном приложении.

представьте себе, что форма заполняется для клиента, который также принимает house_id в качестве входных данных. Затем я делаю следующее в своем контроллере?

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

в целом я запутался, как добавить записи в has_many :through таблицы?

3 77

3 ответа:

Я думаю, что вы можете просто сделать это:

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

или при создании нового дома для клиента:

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

вы также можете добавить через идентификаторы:

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

"лучший способ" зависит от ваших потребностей и того, что чувствует себя наиболее комфортно. Путаница возникает из-за различий в поведении ActiveRecord new и create методы и << оператора.

The new метод

new не будет добавлять запись ассоциации для вас. Вы должны построить House и Agent записи себе:

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

отметим, что @cust.houses.new и House.new эффективно то же самое, потому что вам нужно создать Agent запись в обоих случаях.

The << оператор

как упоминает Миша, вы также можете использовать << оператор по сбору. Это будет только строить Agent модель для вас, вы должны построить House модель:

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

The create метод

create будут строить как House и Agent записи для вас, но вам нужно будет найти Agent модель, если вы намерены вернуть в свой вид или api:

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

в качестве заключительной ноты, если вы хотите, чтобы исключения возникали при создании house вместо этого используйте операторы взрыва (например,new! и create!).

другой способ добавления ассоциаций - это использование столбцов внешнего ключа:

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

или используйте точные имена столбцов, передавая идентификатор связанной записи вместо записи.

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