如何将记录添加到has_many:通过Rails中的关联


97
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表中添加记录感到困惑?


您将在哪个控制器中存储“创建”功能?
Tobias Kolb

Answers:


166

我认为您可以简单地做到这一点:

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

或在为客户建造新房子时:

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

您还可以通过ID添加:

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

16
仅供参考:除非已保存父项,否则您无法创建关联的房屋。
里卡多·奥特罗

那一定是我遇到的这个问题的最优雅的解决方案。为您+1。
丹尼尔·邦纳尔

@RicardoOtero我想我们可以build代替使用create
卡兰(Karan)2013年

@Mischa如果House.find(params [:house_id])为零,我应该如何处理错误。如果params [:house_id]为零,我会收到TypeMismatch错误。但是有没有更好的方法呢?
Vishal

1
我观察到<<在某些情况下使用operator会插入两次。因此,该create方法是最好的方法。
互换

78

“最佳方法”取决于您的需求和最舒适的感觉。混淆来自ActiveRecord new和和create方法以及<<运算符的行为差异。

new方法

new不会为您添加关联记录。您必须构建HouseAgent记录自己:

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

注意@cust.houses.newHouse.new实际上是相同的,因为Agent在两种情况下都需要创建记录。

<<运营商

正如Mischa提到的,您还可以<<在集合上使用运算符。这只会Agent为您建立模型,您必须建立House模型:

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

create方法

create将同时为您建立HouseAgent记录,但是Agent如果您打算将其返回到视图或API ,则需要找到模型:

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

最后一点,如果要在创建时引发异常,请house使用bang运算符(例如new!create!)。


2
该行应agent = @cust.houses.find(house.id)改为阅读agent = @cust.agents.find(house.id)吗?agent“新方法”中的变量agent与后面的示例中的变量不同。可能会使在连接表上使用其他属性的人感到困惑。
vaughan

您能否详细说明如何从联合表“特工”中检索数据而没有N + 1错误示例显示给定客户的所有房屋和相应特工
Ankita.P,2015年

6

添加关联的另一种方法是使用外键列:

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

或使用确切的列名,传递关联记录的ID而不是记录。

agent.house_id = house.id
agent.customer_id = customer.id
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.