2014-05-07 6 views
11

Mi sono bloccato su questo e sicuramente è facile, ma non riesco a trovare la soluzione nei documenti.Come utilizzare Arel :: Nodes :: TableAlias ​​in un'istruzione iniziale dove

ho qualche struttura ad albero e il bambino in cui la clausola che devo filtrare con una "esiste" domanda secondaria:

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

Il Node.where.clause si unisce alle già children_nodes e funziona se io utilizzare due diversi modelli. Ma come faccio a usare l'alias? codice di cui sopra si tradurrà in:

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

E 'così semplice, ma qualcosa che mi manca (sono troppo nuovo per Arel).

+0

Provate con 'current_node.children.as ("children_nodes") Nodo (. In cui (...) esiste)' non testato però. – Pavan

+0

current_node.children.as ("children_nodes"). Il nodo mi fornirà il metodo non definito Nodo per # Micha

risposta

0

il come metodo di generare un oggetto arel che non ha dove oggetto metodo tale relazione l'oggetto Arel genera uno SQL che deve essere eseguito in fondo il suo un selezionare Gestione è possibile utilizzare l'unione e dargli un'altra condizione quindi utilizzare to_sql per esempio:.

arel_obj = current_node.children.as ("children_nodes") dell'Unione (Node.where (....)

sql_string = arel_obj.to_sql

Node.find_by_s ql (sql_string)

ecco alcuni link che potrebbero aiutare http://www.rubydoc.info/github/rails/arel/Arel/SelectManager

0

In Arel, as avrà tutto fino a quel momento e utilizzarlo per creare una sottoquery di nome che si può mettere in una clausola FROM . Ad esempio, current_node.children.as("children_nodes").to_sql stamperà qualcosa di simile:

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

ma suona come quello che si vuole veramente è quello di dare un alias SQL alla tabella nodes. Tecnicamente si può fare con from:

current_node.children.from("nodes AS children_nodes").to_sql 

Ma se lo fai, un sacco di altre cose stanno andando a rompere, perché il resto della query sta ancora cercando di SELECT nodes.* e filtrare WHERE nodes.parent_id = 5.

Quindi penso una scelta migliore è evitare di utilizzare un alias, o scrivere la tua ricerca con 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 

Forse si potrebbe anche far funzionare le cose creando un alias per la tabella interna invece:

current_node.children.where(
    Node.from("nodes n").where("...").select("1").exists 
) 
0

Potrebbe essere possibile utilizzare l'attributo table_alias che è possibile chiamare su Arel :: Table.

Esempio:..

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