3

此的Ruby/Rails總是方式讓我爲難:ActiveRecord的查詢鏈

User.where(:name => "Thiago").limit(3).using(:slave_one) 

這必須從執行左到右,使每個連續的調用有一個接收器。所以我們從User類開始,調用where,它返回一個ActiveRecord::Relation的實例。然後在該實例上調用limit,返回另一個ActiveRecord::Relation實例。然後在該實例上調用using(恰好選擇分片)。整個事情在ActiveRecord::Relation對象內建立一個SQL查詢,我猜。我的問題是「什麼觸發了查詢的實際執行」?它不能在鏈中的任何特定點執行,因爲在鏈中可能會有後續進一步修改查詢。即使在using返回後,該查詢仍然無法執行,因爲它無法知道附加方法是否被添加到鏈中。顯然,它在構建完成後執行查詢,那麼實際上如何調用查詢?


謝謝......我現在看到鏈中的方法的名稱有「語義」。有些會進一步修改正在構建的查詢。最後一個也是唯一的最後一個可能是需要獲取數據的類型。

回答

7

ActiveRecord :: Relation在數據庫中詢問它之前不會與數據庫交談。例如:

User.where(:name => "Thiago").limit(3).using(:slave_one).count 
# talks to the database here ----------------------------^^^^^ 

如果你看一下的ActiveRecord ::關係,你會看到它包含ActiveRecord::QueryMethods和大部分的東西在裏面看起來是這樣的:

def x(*args) 
    relation = clone 
    # merge args into relation 
    relation 
end 

所以關係只是逐個建立一個查詢,直到你做了一些事情需要執行查詢;那麼它將構建適當的SQL,將其發送到數據庫,並且使用數據庫發回的內容(理論上)做一些有用的事情。

還要注意的是每個QueryMethods方法返回一個克隆和修改的關係,所以你可以做這樣的事情:

r1 = User.where(:name => 'Pancakes') 
r2 = r1.limit(3) 

,然後用r1抓住所有的比賽或r2只搶他們三個。

3

這個構造(其中查詢永遠不會執行,因爲你正在構建它)是故意的。它被稱爲延遲加載。

查詢在您首次詢問關係數據時執行。也就是說,如果你有:

@users = User.where(:name => "Thiago").limit(3).using(:slave_one) 
@users.first.name #the query executes here 

通常這是要執行時,他在從查詢數據調用您的視圖模板的第一行。