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

时间:2014-05-07 08:26:10

标签: ruby-on-rails ruby arel table-alias

我坚持这一点并且确实很容易,但我在文档中找不到解决方案。

我有一些树形结构,而且我必须用"过滤的子where where子句存在"子查询:

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

Node.where.clause已经加入了children_nodes,如果我使用两个不同的模型,它就可以工作。但是我该如何使用别名呢?以上代码将导致:

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

这是如此基本,但我缺少的东西(我对你来说太新了)。

3 个答案:

答案 0 :(得分:1)

您可以使用可以在Arel :: Table上调用的属性table_alias

示例:

# 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)

答案 1 :(得分:0)

as方法生成一个arel对象,该对象不具有这样的Relation对象的方法 Arel对象生成一个基本上是执行管理器的sql 你可以使用union并给它另一个条件然后使用to_sql 例如:

  

arel_obj = current_node.children.as(&#34; children_nodes&#34;)。Union(Node.where(....)

     

sql_string = arel_obj.to_sql

     

Node.find_by_sql(sql_string)

这里有一些可能有用的链接 http://www.rubydoc.info/github/rails/arel/Arel/SelectManager

答案 2 :(得分: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
)