Rails使用别名查询连接关联表

时间:2015-03-31 18:17:26

标签: ruby-on-rails join associations

我有一个模型Edge,它通过不同的外键属于另一个模型Node两次:

def Edge < ActiveRecord::Base
    belongs_to :first, class_name: 'Node'
    belongs_to :second, class_name: 'Node'
end

我想使用ActiveRecord执行此查询:

SELECT * FROM edges INNER JOIN nodes as first ON first.id = edges.first_id WHERE first.value = 5

我找到了使用.joins()方法加入关联的方法:

Edge.joins(:first)

但这会产生使用表名而不是关联名的查询,因此在.where()方法中我必须明确使用表名来破坏关联抽象。

Edge.joins(:first).where(nodes: {value: 5})

我还可以在.joins()方法中明确使用SQL查询来定义模型别名:

Edge.joins('INNER JOIN nodes as first ON nodes.id = edges.first_id')

但这会打破更多的抽象。

我认为应该有一种在连接时自动定义表别名的方法。或者也许是一种自己编写这种功能的方法。类似的东西:

def Edge < ActiveRecord::Base
    ...
    def self.joins_alias
        # Generate something like 
        # joins("INNER JOIN #{relation.table} as #{relation.alias} ON #{relation.alias}.#{relation.primary_key} = #{table}.#{relation.foreign_key}")
    end
end

但我无法找到有关访问特定关系信息的任何信息,例如它的名称,外键等。那么我该怎么做呢?

对我而言,这个显而易见的特征是如此复杂,即使Rails已经是第四个主要版本,这似乎也很奇怪。也许我错过了什么?

1 个答案:

答案 0 :(得分:8)

至于Rails 4.2.1,我相信你在ActiveRecord中使用joins时无法提供别名。

如果你想通过第一个节点查询边缘,你可以像你所说的那样进行查询:

Edge.joins(:first).where(nodes: {value: 1})
SELECT "edges".* FROM "edges" INNER JOIN "nodes" ON "nodes"."id" = "edges"."first_id" WHERE "nodes"."value" = 1

但是如果你必须使用两个节点进行查询,你仍然可以像这样使用joins

Edge.joins(:first, :second).where(nodes: {value: 1}, seconds_edges: {value: 2})
SELECT "edges".* FROM "edges" INNER JOIN "nodes" ON "nodes"."id" = "edges"."first_id" INNER JOIN "nodes" "seconds_edges" ON "seconds_edges"."id" = "edges"."second_id" WHERE "nodes"."value" = 1 AND "seconds_edges"."value" = 2