具有多个表/约束的联接或具有辅助约束的has_one_through

时间:2018-07-06 11:20:20

标签: sql ruby postgresql activerecord ruby-on-rails-5.1

我为人为的例子表示歉意

一个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 

或禁止使用多个表(使用ruby散列)或使用具有额外表约束的has_one_through的Join查询。

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

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

1 个答案:

答案 0 :(得分:1)

对不起,我必须使用答案来获取更多信息。 可能有这种情况吗?

| 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作为要在表Journey中查找的键,则将获取ID 1,2,3和4。

在您回复之后,这种情况永远不会发生,因为验证过滤器不允许这样做。 因此,所需的是使用双外键office_idhouse_id访问旅程表。

最好的解决方案是

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

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

end

但rails尚不支持多个外键。

一种可能的解决方法是为journey类定义实例方法Person

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