Как использовать Arel:: Nodes:: TableAlias в начале, где оператор
Я застрял на этом и, конечно же, легко, но я просто не могу найти решение в документах.
У меня есть некоторая древовидная структура и предложение child where, которое я должен фильтровать с помощью суб-запроса "exist":
current_node.children.as("children_nodes").where(Node.where(...).exists)
Node.where.clause уже присоединяется к children_nodes и работает, если я использую две разные модели. Но как я могу использовать псевдоним? Вышеуказанный код приведет к:
NoMethodError (undefined method `where' for #<Arel::Nodes::TableAlias
Это так просто, но что-то мне не хватает (я слишком новичок в isl).
Ответы
Ответ 1
как метод генерирует объект isl, который не имеет метода, такого как объект Relation
объект Arel генерирует sql для выполнения в основном своего диспетчера select
вы можете использовать union и дать ему другое условие, а затем использовать to_sql
например:
arel_obj = current_node.children.as( "children_nodes" ). Союз (Node.where(....)
sql_string = arel_obj.to_sql
Node.find_by_sql (SQL_string)
вот некоторые ссылки, которые могут помочь
http://www.rubydoc.info/github/rails/arel/Arel/SelectManager
Ответ 2
В Arel, 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
)
Ответ 3
Возможно, вы сможете использовать атрибут table_alias
, который вы можете вызвать в таблице Arel::.
Пример:
# 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)