2013-06-26 58 views
5

鑑於2個ActiveRecord的關係,不同的表生成SQL語句:如何合併(鏈接)2間的關係在軌道4個

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

這個工作在軌道/ 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" 

我認爲它的工作原因是merge忽略了查詢中的任何不存在的關聯。

但Rails的更加顯得很迂腐,失敗:

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

所以,問題是我怎麼可以從字面上合併2間的關係,而不Rails的是擔心正確性(我的規格承擔的責任)?

+0

檢查由Rails內部使用的Arel gem - https://github.com/rails/arel以及這裏的一些示例/規格https://github.com/rails/arel/tree/master/test你可能會得到一些更多的見解。 –

+0

@OtoBrglez在那裏找不到任何指針。你有什麼? –

回答

0

你能描述一下你的模型和他們的關係嗎?

對我來說,它的工作是這樣的:

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) 

=>用戶負載(0.5毫秒)選擇users * FROM users WHERE(users.first_name LIKE '%桑迪%')AND(facebook_friends.last_name等。 '%約翰%')

=> Mysql2 ::錯誤:未知列 'facebook_friends.last_name' 在 'where子句':SELECT users * FROM users WHERE(users.first_name LIKE '%桑迪%')AND( facebook_friends.last_name LIKE'%John%')

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

=>用戶負載(0.6ms)SELECT users。*從users INNER JOIN facebook_friends ON facebook_friendsuser_uid = usersuid WHERE(users.first_name LIKE '%桑迪%')AND(facebook_friends.last_name LIKE '%約翰%')

=> []

0

驚人scuttle.io將您的SQL如下:

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 
)