如何合并(链接)Rails 4中不同表上的2个关系

时间:2022-10-15 23:21:15

Given 2 ActiveRecord relations that generate following SQL:

给定2个生成以下SQL的ActiveRecord关系:

  • relation a = SELECT comments.* FROM comments INNER JOIN attachments ON attachments.comment_id = comments.id WHERE attachment.name ILIKE '%foo%
  • 关系a = SELECT注释。* FROM注释INNER JOIN附件ON attachments.comment_id = comments.id WHERE attachment.name ILIKE'%foo%
  • relation b = SELECT attachments.* FROM attachments INNER JOIN users ON attachments.user_id = users.id WHERE users.other_conditions
  • 关系b = SELECT附件。* FROM附件INNER JOIN用户ON attachments.user_id = users.id WHERE users.other_conditions

This worked in Rails/ActiveRecord 3:

这在Rails / ActiveRecord 3中有效:

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"

I think it worked because the merge was ignoring any non-existing associations on the queries.

我认为这很有效,因为合并忽略了查询中任何不存在的关联。

But Rails 4 is much more pedantic and fails with:

但是Rails 4更加迂腐,并且失败了:

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

So the question is how can I literally merge the 2 relations without Rails being worried about the correctness (my specs take responsibility for that)?

所以问题是如果没有Rails担心正确性(我的规范对此负责),我怎么能真正合并这两种关系呢?

2 个解决方案

#1


0  

Can you describe your models and their relations a little more?

你能描述一下你的模特和他们的关系吗?

For me it worked like this:

对我来说它的工作方式如下:

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)

=> User Load (0.5ms) SELECT users.* FROM users WHERE (users.first_name LIKE '%Sandy%') AND (facebook_friends.last_name LIKE '%John%')

=>用户加载(0.5ms)SELECT用户。* FROM users WHERE(users.first_name LIKE'%Sandy%')AND(facebook_friends.last_name LIKE'%John%')

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

=> Mysql2 ::错误:'where子句'中的未知列'facebook_friends.last_name':SELECT users。* FROM users WHERE(users.first_name LIKE'%Sandy%')AND(facebook_friends.last_name LIKE'%John%')

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

=> User Load (0.6ms) SELECT users.* FROM users INNER JOIN facebook_friends ON facebook_friends.user_uid = users.uid WHERE (users.first_name LIKE '%Sandy%') AND (facebook_friends.last_name LIKE '%John%')

=>用户加载(0.6ms)SELECT用户。* FROM用户INNER JOIN facebook_friends ON facebook_friends.user_uid = users.uid WHERE(users.first_name LIKE'%Sandy%')AND(facebook_friends.last_name LIKE'%John%')

=> []

=> []

#2


0  

The amazing scuttle.io transforms your sql as follows:

惊人的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
)

#1


0  

Can you describe your models and their relations a little more?

你能描述一下你的模特和他们的关系吗?

For me it worked like this:

对我来说它的工作方式如下:

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)

=> User Load (0.5ms) SELECT users.* FROM users WHERE (users.first_name LIKE '%Sandy%') AND (facebook_friends.last_name LIKE '%John%')

=>用户加载(0.5ms)SELECT用户。* FROM users WHERE(users.first_name LIKE'%Sandy%')AND(facebook_friends.last_name LIKE'%John%')

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

=> Mysql2 ::错误:'where子句'中的未知列'facebook_friends.last_name':SELECT users。* FROM users WHERE(users.first_name LIKE'%Sandy%')AND(facebook_friends.last_name LIKE'%John%')

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

=> User Load (0.6ms) SELECT users.* FROM users INNER JOIN facebook_friends ON facebook_friends.user_uid = users.uid WHERE (users.first_name LIKE '%Sandy%') AND (facebook_friends.last_name LIKE '%John%')

=>用户加载(0.6ms)SELECT用户。* FROM用户INNER JOIN facebook_friends ON facebook_friends.user_uid = users.uid WHERE(users.first_name LIKE'%Sandy%')AND(facebook_friends.last_name LIKE'%John%')

=> []

=> []

#2


0  

The amazing scuttle.io transforms your sql as follows:

惊人的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
)