4

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

  • 关系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

这在 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"

我认为它有效,因为它merge忽略了查询中任何不存在的关联。

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

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

所以问题是我如何才能在 Rails 不担心正确性的情况下真正合并这两个关系(我的规范对此负责)?

4

2 回答 2

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.5ms) SELECT users.* FROM usersWHERE (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%')

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

=> 用户负载 (0.6ms) SELECT users.* FROM usersINNER JOIN facebook_friendsON facebook_friendsuser_uid= usersuidWHERE (users.first_name LIKE '%Sandy%') AND (facebook_friends.last_name LIKE '%John%')

=> []

于 2013-10-03T08:03:56.160 回答
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
)
于 2014-10-16T02:49:24.970 回答