2013-06-26 8 views
5

Attribuite 2 relazioni ActiveRecord che generano seguenti SQL:Come unire (link) 2 Relazioni su diversi tavoli in Rails 4

  • relazione a = SELECT comments.* FROM comments INNER JOIN attachments ON attachments.comment_id = comments.id WHERE attachment.name ILIKE '%foo%
  • relazione b = SELECT attachments.* FROM attachments INNER JOIN users ON attachments.user_id = users.id WHERE users.other_conditions

Questo ha funzionato in Rails/ActiveRecord :

puts a.merge(b).to_sql # Rails 3 
> "SELECT comments.* FROM comments INNER JOIN attachments ON attachments.comment_id = comments.id INNER JOIN users ON attachments.user_id = users.id WHERE attachment.name ILIKE '%foo% AND users.other_conditions" 

Penso che abbia funzionato perché lo merge ignorava qualsiasi associazione non esistente nelle query.

Ma Rails è molto più pedante e fallisce con:

puts a.merge(b).to_sql # Rails 4 
> ActiveRecord::ConfigurationError: Association named 'user' was not found on Comment; perhaps you misspelled it? 

Quindi la domanda è come posso letteralmente unire i 2 rapporti senza rotaie di essere preoccupato per la correttezza (mie specifiche assumersi la responsabilità per quella)?

+0

Controlla la gemma Arel utilizzata internamente da Rails - https://github.com/rails/arel e alcuni esempi/specifiche qui https://github.com/rails/arel/tree/master/test potresti ottenere alcuni più intuizione. –

+0

@OtoBrglez non riesce a trovare alcun puntatore lì. Hai qualche? –

risposta

0

Puoi descrivere un po 'di più i tuoi modelli e le loro relazioni?

Per me ha funzionato così:

class User 
    has_many :facebook_friends 
end 

class FacebookFriend 
    belongs_to :user 
end 

a = User.where("users.first_name LIKE '%Sandy%'") 
b = FacebookFriend.where("facebook_friends.last_name LIKE '%John%'") 
a.merge(b) 

=> carico di utenti (0,5 ms) SELECT * FROM usersusers WHERE (users.first_name LIKE '% Sandy%') e (facebook_friends.last_name LIKE. '% John%')

=> Mysql2 :: Error: Unknown column 'facebook_friends.last_name' in 'where clause':. SELEZIONARE users * FROM WHERE users (users.first_name LIKE '% Sandy%') e (facebook_friends.last_name LIKE '% John%')

a.joins(:facebook_friends).merge(b) 

=> carico di utenti (0.6ms) Selezionare users. * FROM users INNER JOIN facebook_friends ON facebook_friends. user_uid = users. uid WHERE (users.first_name LIKE '% Sandy%') e (facebook_friends.last_name LIKE '% John%')

=> []

0

L'incredibile scuttle.io trasforma il vostro SQL come segue:

Comment.select(Comment.arel_table[Arel.star]).where(
    Attachment.arel_table[:name].and(User.arel_table[:other_conditions]) 
).joins(
    Comment.arel_table.join(Attachment.arel_table).on(
    Attachment.arel_table[:comment_id].eq(Comment.arel_table[:id]) 
).join_sources 
).joins(
    Comment.arel_table.join(User.arel_table).on(
    Attachment.arel_table[:user_id].eq(User.arel_table[:id]) 
).join_sources 
)