Как использовать 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