在 The Rails Tutorial 第 2 版第 11 章的清单 11.45 中,Micropost
类的 from_users_followed_by
类方法定义如下:
class Micropost < ActiveRecord::Base
...
def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
user_id: user.id)
end
end
在本章的脚注 13 中,有一个指向此博客文章的链接,其中指出,如果要创建子选择字符串,可以使用 ActiveRecord 内部方法construct_finder_sql
send
方法。 因此,我尝试将followed_user_ids
字符串替换为:
followed_user_ids = Relationship.send(:construct_finder_sql,
select: "followed_id",
conditions: { follower_id: :user_id })
唯一的问题是construct_finder_sql
在 Rails 3 中被折旧了,所以除了不知道我写的内容是否正确之外,我无论如何都不能使用它。 那么,是否有一种 Rails 3 方法可以使用 ActiveRecord(最好仍使用 :user_id
参数)创建子选择字符串,可以在这种情况下工作?
您可以将 seb-select 构建为单独的查询,然后使用 to_sql
获取 SQL:
def self.from_users_followed_by(user)
followed = Relationship.select(:followed_id)
.where(:follower_id => user.id)
.to_sql
where("user_id in (#{followed}) or user_id = :user_id", :user_id => user.id)
end
像M.select(...).where(...)
只是构建ActiveRecord::Relation
实例之类的东西,而那些实例则逐个构建查询,在您请求一些结果(以某种方式)之前,不会将任何内容发送到数据库。因此,您可以使用 AREL 的东西来构建查询,然后to_sql
它以获取 SQL 版本。