Rails Arel和Active Record谓词

Mic*_*son 2 sql activerecord ruby-on-rails arel

我可能对Rails中的Arel对象缺乏一些了解.

你可以这样做:

u = User.arel_table
Run Code Online (Sandbox Code Playgroud)

然后和疯狂的查询添加如:

u.join(:microposts)
Run Code Online (Sandbox Code Playgroud)

(隐式.on(users [:user_id])).

但是,如何将Arel关系转换为Rails对象列表?

更新

这是一个更好的例子.我刚刚完成了Michael Hartl的Rails教程,他在Micropost控制器中做了类似的事情:

  followed_ids  = %(SELECT followed_id FROM relationships WHERE follower_id = :user_id)
  where("user_id in (#{followed_ids}) OR user_id = :user_id", :user_id => user)
Run Code Online (Sandbox Code Playgroud)

我讨厌原始的SQL.所以我想重构,到目前为止我所拥有的最好的是:

followed_ids  = Relationship.select(:followed_id).where(:follower_id => user) 
where("user_id in (#{followed_ids.to_sql}) OR user_id = :user_id", :user_id => user)
Run Code Online (Sandbox Code Playgroud)

我曾经将.map(&:follow_id).join(",")添加到关系选择中,它也有效,但是你在内存中有所有id,而不是要处理的数据库的短选择语句.

我的问题是,似乎我需要做一个.to_sql来提供给哪里并让它快乐,当它拥有它需要的所有东西来返回我的对象​​.我正在考虑切换到可以很好地完成子查询的Squeel,但我想了解Arel.

aNo*_*ble 5

那么你可以做到

User.joins(User.arel_table.joins(:microposts))
Run Code Online (Sandbox Code Playgroud)

但是没有多大意义,因为你可以做到User.joins(:microposts)并得到相同的结果.但是如果你必须创建一些更复杂的连接,它可能很方便.

这样的事情可能很有用.

User.where(User.arel_table[:name].matches('John%'))
Run Code Online (Sandbox Code Playgroud)

记住,虽然你可以利用Rails中的一些核心Arel的东西,但通常更好地坚持使用更简单的方法,.where(:name=>'John')或者.where('name LIKE ?', 'John%')因为Rails无论如何都会将它们变成幕后的Arel对象.