如何在初始where语句中使用Arel::Nodes::TableAlias?

12

我被卡住了,这个问题肯定很简单,但是我在文档中找不到解决方案。

我有一些树形结构和一个子查询的where子句,我必须使用"exists"子查询来过滤孩子节点:

current_node.children.as("children_nodes").where(Node.where(...).exists)

Node.where.clause已经连接到children_nodes,如果我使用两个不同的模型,它可以正常工作。但是我如何使用别名?上面的代码将导致:

NoMethodError (undefined method `where' for #<Arel::Nodes::TableAlias

很基础的问题,但是我还不明白(因为我对arel还不熟悉)。


尝试使用 current_node.children.as("children_nodes").Node.(where(...).exists),虽然未经测试。 - Pavan
current_node.children.as("children_nodes").Node会给我返回#Arel::Nodes::TableAlias的未定义方法Node。也许你搞混了什么? - Micha
3个回答

5
您可以使用属性table_alias,并在Arel::Table上调用它。
示例:
# works
users = User.arel_table
some_other_table = Post.arel_table
users.table_alias = 'people'
users.join(some_other_table)

# doesn't work
users = User.arel_table.alias('people')
some_other_table = Post.arel_table
users.join(some_other_table)

2
警告:arel_table 方法总是返回相同的对象(至少在 Rails 4.2 中),因此更改 table_alias 会产生副作用。使用 User.arel_table.dup 可以正常工作。 - Michaël Witrant

0
在 Arel 中,as 会获取到该点之前的所有内容,并使用它来创建一个命名子查询,您可以将其放入 FROM 子句中。例如,current_node.children.as("children_nodes").to_sql 将打印出类似以下的内容:
(SELECT nodes.* FROM nodes WHERE nodes.parent_id = 5) AS children_nodes

但是你真正想要的似乎是为nodes表给予一个SQL别名。技术上说,你可以通过from实现:

current_node.children.from("nodes AS children_nodes").to_sql

但是如果你这样做,很多其他的东西都会出问题,因为查询的其余部分仍然在尝试 SELECT nodes.* 并过滤 WHERE nodes.parent_id = 5

所以我认为更好的选择是避免使用别名,或者使用 find_by_sql 编写你的查询:

Node.find_by_sql <<-EOQ
    SELECT n.*
    FROM   nodes n
    WHERE  n.parent_id = 5
    AND EXISTS (SELECT 1
                FROM   nodes n2
                WHERE  ....)
EOQ

也许你可以通过给内部表起别名来使事情正常工作:
current_node.children.where(
  Node.from("nodes n").where("...").select("1").exists
)

0

as方法生成一个Arel对象,该对象不具有where方法,类似于Relation对象。 Arel对象生成要执行的SQL语句,基本上是一个select manager。 您可以使用union并给它另一个条件,然后使用to_sql。 例如:

arel_obj = current_node.children.as("children_nodes").Union(Node.where(....)

sql_string = arel_obj.to_sql

Node.find_by_sql(sql_string)

这里有一些链接可能会有所帮助 http://www.rubydoc.info/github/rails/arel/Arel/SelectManager


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接