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

Posted

技术标签:

【中文标题】如何将记录添加到has_many:通过rails中的关联【英文标题】:how to add records to has_many :through association in rails 【发布时间】:2011-11-09 23:20:32 【问题描述】:
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

如何将Customer 添加到Agents 模型中?

这是最好的方法吗?

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

【问题讨论】:

你会将函数“create”存储在哪个控制器中? 【参考方案1】:

我认为你可以简单地这样做:

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

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

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

你也可以通过 ids 添加:

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

【讨论】:

仅供参考:除非父级已保存,否则您无法创建关联的房屋。 这必须是我遇到的这个问题的最优雅的解决方案。为你 +1。 @RicardoOtero 我想我们可以使用build 而不是create @Mischa 如果 House.find(params[:house_id]) 为 nil,我应该如何处理错误。如果 params[:house_id] 为 nil,我收到 TypeMismatch 错误。我已经在使用救援。但是有什么更好的方法吗?? 我观察到使用&lt;&lt; 运算符在某些情况下会插入两次。所以create方法是最好的方法。【参考方案2】:

“最佳方式”取决于您的需求以及最舒适的方式。混淆来自 ActiveRecord 的 newcreate 方法和 &lt;&lt; 操作符的行为差异。

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 记录。

&lt;&lt; 运算符

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

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

create 方法

create 将为您构建 HouseAgent 记录,但如果您打算将其返回到您的视图或 api,则需要找到 Agent 模型:

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

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

【讨论】:

应该将agent = @cust.houses.find(house.id) 行改为agent = @cust.agents.find(house.id) 吗? “新方法”中的agent 变量与后面示例中的agent 不同。可能会给在连接表上使用其他属性的人造成一些混淆。 您能否详细说明从联合表 Agents 中检索数据而没有显示给定客户的所有房屋和相应代理的 N+1 个错误示例【参考方案3】:

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

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

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

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

【讨论】:

以上是关于如何将记录添加到has_many:通过rails中的关联的主要内容,如果未能解决你的问题,请参考以下文章

Rails中如何通过对象同时保存多个has_many?

rails内的class关于添加了has_many或者belongs_to后如何动态添加一些额外的方法 ?

Rails has_many 关联如何保证每条关联记录只有一个?

带有has_many的模型中的属性总和:通过关联在Rails 5中不起作用

如何通过rails中的关联定义has_many

Rails:如何通过 has_many 进行优雅的调用