12

確かに簡単ですが、ドキュメントで解決策を見つけることができません。

いくつかのツリー構造と、「存在する」サブクエリでフィルタリングする必要がある子 where 句があります。

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

Node.where.clause は既に children_nodes に結合されており、2 つの異なるモデルを使用すると機能します。しかし、エイリアスを使用するにはどうすればよいですか? 上記のコードは次のようになります。

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

それはとても基本的なことですが、私が見逃しているものがあります (私はあまりにも新しいので、問題を解決することはできません)。

4

3 に答える 3

0

as メソッドは、relation オブジェクトなどの where メソッドを持たない arel オブジェクトを生成します。Arel オブジェクトは、実行する SQL を生成します。基本的には、ユニオンを使用して別の条件を指定し、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

于 2014-10-28T14:55:27.040 に答える
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
)
于 2016-02-17T01:36:38.580 に答える