2017-03-16 104 views
1

讓我們來看看Rails 4.2.x應用程序,我們有兩個表格文章和作者,我們希望使用Arel來獲取由作者創作的文章,其中name = ='卡爾'。 (在這種情況下,我們會很樂意與Active Record的加入,但是這僅僅是保持示例簡單。)Arel:與加入的Arel :: SelectManager之間的主動關係

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 

現在我們可以通過做回來數組(類數組)職位:

> 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, 
    ... 
    ] 

所以我們得到樁的陣列,而不是一個有效記錄的關係:

> Post.find_by_sql(my_query).class 
=> Array 

而且注射經理到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 

我想我一定會錯過一些東西。簡而言之:如何從上面的my_query之類的選擇管理器(或其他選擇管理器完成相同的事情)中獲得活動的記錄關係。

回答

2

無法從sql字符串中獲取ActiveRecord ::從Arel :: SelectManager的關係。您有兩種方法通過ActiveRecord加載數據:

  1. 在Arel中執行所有查詢邏輯。在這種情況下,您不能使用任何ActiveRecord :: Relation方法。但是你在Arel中有相同的功能。在您的例子中,你可以通過阿雷爾限量:

    my_query.take(10) 
    
  2. 另一種方式是在ActiveRecord的::關係的方法來使用阿雷爾。你可以重寫查詢是這樣的:

    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 
    

在這種情況下,你可以使用my_query如的ActiveRecord ::關係