加入多个 tables/constraints 或 has_one_through 与次级约束

Joins with multiple tables/constraints OR has_one_through with secondary constraint

我为人为的例子道歉

A person 有一个 journey 但没有直接连接到那个 journey,而是通过它们的 houseoffice 连接。

一个person belongs_to a house,一个house has_many people

一个person belongs_to a office,一个office has_many people

一个journey belongs_to a house,一个house has many journeys

一个journey belongs_to a office,一个office has many journeys

                         +---------+
       +---Belongs-To---->         <----Belongs-To--+
       |                 |  House  |                |
       |  +-Has-Many-----+         +-----Has-Many-+ |
       |  |              +---------+              | |
       |  |                                       | |
+------+--v+                                     +v-+--------+
|          |                                     |           |
|  Person  |                                     |  Journey  |
|          |                                     |           |
+------+--^+                                     +^-+--------+
       |  |                                       | |
       |  |              +----------+             | |
       |  +-Has-Many-----+          +----Has-Many-+ |
       |                 |  Office  |               |
       +----Belongs-To--->          <---Belongs-To--+
                         +----------+

按照这个人为的例子,允许以下内容的最佳方法是什么:

person.journey 

OR 禁止具有多个 table 的 Join 查询(使用 ruby 哈希)或使用具有额外 table 约束的 has_one_through

我们确实有一个 sql 查询,但如果可以的话,我们宁愿避免使用原始 sql,但它看起来像这样:

Person
.joins('INNER JOIN journeys
        ON journeys.office_id = person.office_id
        AND journeys.house_id = person.house_id')

抱歉,我必须使用答案才能获得更多信息。 有没有可能有这种情况?

| Person                      |   | Journey                     |
|----+-----------+------------|   |----+-----------+------------|
| id | office_id | house_id   |   | id | office_id | house_id   |
|----+-----------+------------|   |----+-----------+------------|
| 1  | 1         | 1          |   | 1  | 1         | 1          |
| 2  | 1         | 1          |   | 2  | 1         | 1          |
| 3  | 1         | 1          |   | 3  | 1         | 1          |
| 4  | 1         | 1          |   | 4  | 1         | 1          |

如何在本案例的数据上查到具体人物的行程?

如果您考虑 person = Person.find(1) 并使用 person.office_idperson.house_id 作为在 table 旅程中查找的键,您将获取 ID 1、2、3 和4. 不只是一次旅行。

根据您的回复,这种情况从未发生过,因为验证过滤器不允许。 因此,需要使用双外键访问 Journey table:office_idhouse_id.

最好的解决方案是

class Person < ActiveRecord::Base
  belongs_to :office
  belongs_to :house

  has_one :journey, foreign_keys: [:house_id, :office_id]

end

但是rails还不支持多外键。

一种可能的解决方法是为 Person class:

定义实例方法 journey
class Person < ActiveRecord::Base
  belongs_to :office
  belongs_to :house

  def journey
    Journey.where(office_id: office_id, house_id: house_id).last
  end

end

所以你可以调用person.journey.