如何实际使用has_many:通过并建立关系

时间:2014-07-12 07:51:17

标签: ruby-on-rails activerecord ruby-on-rails-4 has-many-through

有很多关于如何设置has_many :through的教程,但还没有足够的关于如何实际操作的教程!

我有一个由Inventories加入的RequestsBookings表格。例如:可能有3个贷款人在库存中有帐篷,每个贷款人都有3个其他借款人要求。我想要做的是对于库存中的3个帐篷中的每个帐篷,向贷款人显示请求帐篷的3个借款人的列表。然后贷款人可以选择他/她想成为最终借款人的人。

我想知道这应该如何运作,但不知道它是否正确,所以请提供以下建议!该操作由Requests控制器驱动。让我们来看一个示例,其中Inventories表已经有3个帐篷,[1, 2, 3]。让我们说Borrower Pat为帐篷提交Request_ID 1

  1. 我是否应该创建3个新的Bookings所有Request_ID 1然后Inventory_ID [1, 2, 3]以获得所有可想到的组合?像

    这样的东西

    Inventory.where(name: "tent").each { |inventory| @request.bookings.create(inventory_id: inventory.id) }

  2. 然后在BookingsRequest中使用Inventory主键作为外键是否正确?这意味着在借款人Pat提交请求后,bookings_id将一直为空,直到贷方2接受为止,此时bookings_id等于与Request_ID 1和{{1}的组合相匹配的ID }}

  3. 现在让我们说当发布Inventory_ID 2并发出Request时,我会向贷方发送电子邮件。然而,我意识到如果3个借款人在同一时期想要她的帐篷,我不想打扰贷款人泰勒。我会在第一时间给她发电子邮件,然后是她在登录时说出是或否的随后的电子邮件。在这种情况下,可以在创建操作中查询Bookings表,例如(在上面展开)

  4. -

    Bookings

    上面的代码可能有缺陷,我只是想知道这应该如何工作的理论。

2 个答案:

答案 0 :(得分:1)

加入表格

首先,has_many :through使用连接表 - 一个用于为其他表标识两个不同foreign_keys的中央表。这就是提供through功能的原因:

enter image description here

有些琐事:

  • has_and_belongs_to_many表名为[plural_model_1]_[plural_model_2],模型需要按字母顺序排列(entries_users

  • has_many :through联接表可以被称为任何内容,但通常称为[alphabetical_model_1_singular]_[alphabetical_model_2_plural]

-

<强>模型

has_many :through模型通常按如下方式构建:

#app/models/inventory.rb
Class Inventory < ActiveRecord::Base
   has_many :bookings
   has_many :requests, through: :bookings
end

#app/models/booking.rb
Class Booking < ActiveRecord::Base
   belongs_to :inventory
   belongs_to :request
end

#app/models/request.rb
Class Request < ActiveRecord::Base
   has_many :bookings
   has_many :requests, through: :bookings
end

-

<强>代码

你的代码非常臃肿 - 你做这样的事情要好得多:

#app/controllers/inventories_controller.rb
Class InventoriesController < ApplicationController
   def action
      @tents = Inventory.where name: "tent"
      @tents.each do |tent|
          booking = Booking.find_or_create_by inventory_id: tend.id
          AlertMail.mail_to_lender(tent).deliver if booking.is_past_due?
      end
   end
end

#app/models/booking.rb
Class Booking < ActiveRecord::Base
   def is_past_due?
      ...logic here for instance method
   end
end

已使用find_or_create_by

你应该只引用一次 - 它被称为DRY(不要自己重复)

答案 1 :(得分:1)

我在问这个问题时表现不佳。我想知道的是如何在DB和模型文件中设置所有内容后创建实际的关联。

如果要创建与现有A记录处于多对多关系中的B记录,则它与A.Bs.create的语法相同。对我来说更重要的是如何链接已经存在的A和B,在这种情况下答案是A.B_ids += B_id

另外两件事:

  1. 更明显:如果你以某种方式创建/链接某些东西,那么另一种方式是自动的吗?是的,当然。在多对多关系中,如果您已完成A.B_ids += B_id,则不再需要执行B.A_ids + = A_id`。

  2. 不太明显:如果A和B由表AB连接,表AB的主键不需要添加到A或B.Rails要求你担心AB表少尽可能地,搜索,构建等都可以通过A.BB.A代替A.AB.BB.AB.A

  3. 完成