Как использовать Arel::Nodes::TableAlias ​​в начальном операторе 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 ответа

Вы могли бы использовать атрибут 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)

В Ареле as будет принимать все до этого момента и использовать его для создания именованного подзапроса, который вы можете поместить в FROM пункт. Например, current_node.children.as("children_nodes").to_sql напечатает что-то вроде этого:

(SELECT nodes.* FROM nodes WHERE nodes.parent_id = 5) AS children_nodes

Но похоже, что вы действительно хотите, чтобы дать псевдоним SQL для nodes Таблица. Технически вы можете сделать это с 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
)

Метод as генерирует объект arel, у которого нет такого метода, как объект Relation. Объект Arel генерирует sql для выполнения, в основном, с помощью менеджера выбора, который вы можете использовать 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

Другие вопросы по тегам