sun*_*ess 4 activerecord arel ruby-on-rails-4
让我们拥有一个Rails 4.2.x应用程序,并且拥有两个表的帖子和作者,并且我们想使用Arel来获取由作者=='Karl'创作的帖子。(在这种情况下,我们可能对Active Record联接感到满意,但这只是为了使示例简单。)
posts = Arel::Table.new :posts
authors = Arel::Table.new :authors
my_query = posts.project(Arel.star)
.join(authors)
.on(posts[:author_id].eq(authors[:id]))
.where(authors[:name].eq('Karl'))
> my_query.class
=> Arel::SelectManager
Run Code Online (Sandbox Code Playgroud)
现在,我们可以通过执行以下操作来获取帖子数组(类Array):
> Post.find_by_sql my_query
[master] Post Load (3.1ms) SELECT * FROM "posts" INNER JOIN "authors"
ON "posts"."author_id" = "authors"."id"
WHERE "authors"."name" = 'Karl'
=> [#<Post:0x005612815ebdf8
id: 7474,
...
]
Run Code Online (Sandbox Code Playgroud)
因此,我们确实获得了一系列帖子,而不是活动记录关系:
> Post.find_by_sql(my_query).class
=> Array
Run Code Online (Sandbox Code Playgroud)
同时将经理注入Post.where无法正常工作
> Post.where my_query
=> #<Post::ActiveRecord_Relation:0x2b13cdc957bc>
> Post.where(my_query).first
ActiveRecord::StatementInvalid: PG::SyntaxError:
ERROR: subquery must return only one column
SELECT "posts".* FROM "posts"
WHERE ((SELECT * FROM "posts" INNER JOIN "authors" ON "posts"."author_id" = "authors"."id" WHERE "authors"."name" = 'Karel'))
ORDER BY "posts"."id" ASC LIMIT 1
Run Code Online (Sandbox Code Playgroud)
我在想我一定很想念东西。简而言之:如何从上面的my_query这样的选择管理器(或另一个完成相同任务的选择管理器)中获得活动记录关系。
您既不能从Arel :: SelectManager中获取ActiveRecord :: Relation,也不能从SQL字符串中获取。您有两种通过ActiveRecord加载数据的方式:
在Arel中执行所有查询逻辑。在这种情况下,您不能使用任何ActiveRecord :: Relation方法。但是您在Arel中具有相同的功能。在您的示例中,您可以通过Arel设置限制:
my_query.take(10)
Run Code Online (Sandbox Code Playgroud)其他方法是在ActiveRecord :: Relation方法中使用Arel。您可以这样重写查询:
posts = Arel::Table.new :posts
authors = Arel::Table.new :authors
join = posts.join(authors).
on(posts[:author_id].eq(authors[:id])).
join_sources
my_query = Post.
joins(join).
where(authors[:name].eq('Karl'))
> my_query.class
=> ActiveRecord::Relation
Run Code Online (Sandbox Code Playgroud)在这种情况下,您可以my_query用作ActiveRecord :: Relation
| 归档时间: |
|
| 查看次数: |
1801 次 |
| 最近记录: |