2012-07-02 19 views
0

在我的應用程序中,我有一個複雜的數據庫結構。爲了爲一個調用生成JSON響應,我需要從許多連接的表中獲取數據。如何避免再次調用數據庫當我已經擁有全部需要的SQL調用結果時

我創建了一個SQL查詢,獲取我需要的所有數據(使用rails'includes)。然而,現在我認爲我的結果是,我無法弄清楚什麼是實際呈現它的正確方法。

一個簡單的例子,不是我的實際代碼:比方說,我有項目包含子項目包含任務和查詢返回他們所有的一些嵌套結構,根據一些過濾邏輯。

class Project < ActiveRecord::Base 
    ... 
    def with_sub_projects_visible_by(user) 
    includes(...complex join with sub projects and tasks...) 
    .where(...complex condition...) 
    end 
end 

在控制器我有這樣的事情:

def show 
    @project_with_full_details = Project.find(params[:id]).with_sub_projects_visible_by(current_user) 
    end 

有沒有寫,這將使得包含從@project_with_full_details的所有數據,而無需再次調用數據庫中的頁面簡潔視圖代碼的方法嗎?從我的嘗試中,只需撥打@project_with_full_details.sub_projects並不能解決問題。它調用數據庫並獲取相關子項目的完整列表,而不是應該包含在查詢結果中的已過濾列表。

(我使用Rabl的對我的看法,因爲我渲染JSON,但它是那麼重要,ERB例如將完全罰款)

+0

只是在執行'includes(:tasks)'應該爲您做好急切的加載並且只做一個連接查詢來獲取對象和相關的任務關聯。 '包括(...複雜的加入子項目和任務...)'不會最大限度地發揮作用,如果你想用自定義查詢做一個非常複雜的連接,你需要'join()'方法 – VelLes

回答

1

的ActiveRecord提供了一個預加載了導致的Rails只加載的關聯來自數據庫的對象一次(它也發生在頁面加載之前)。

對於你的榜樣,它可能會是這個樣子:

@project = Project.find(params[:id]) 
ActiveRecord::Associations::Preloader.new(
    @project, [ :subprojects, subprojects: :tasks] 
) 

這將至少給你只能在運行SQL一旦預期的效果。

如果你的模型看起來是這樣的:

class Project 
    has_many :users 
    has_many :sub_projects 
    has_many :tasks, through: :sub_projects 
    ... 
end 

那麼也許你可以這樣定義subprojects_for(user)的方法。那麼你應該可以沿着這些線做些事情:

# controller 
@project = Project.find(params[:id]) 
@subprojects = @project.subprojects_for(current_user) 

# haml 
.project 
    = @project.title 
    - @project.subprojects_for(current_user).each do |subproject| 
    = Something for subprojects... 
    - subproject.tasks.each do |task| 
     = You get the idea 

雖然真正的魔法應該發生在preloader中。我假設你已經查看了服務器日誌,看到SQL正在運行多次?

+0

謝謝快速回答。我確實查看了服務器日誌,發現SQL正在運行多次。我嘗試了類似這種方法,但我的問題是,subprojects_for(like)方法在我的情況下非常複雜,並轉到數據庫。你使用預加載器會如何顯示,導致它在內存中運行? – davidrac

+0

如果不知道'with_sub_projects_visible_by'需要做什麼,很難說。大概你有'User','Subproject'和'SubprojectPermission'模型,或者這些模型?你能不能做一些像SubprojectPermission.where(user:4).map(&:subproject)'? –

+0

編號計算子子程序的權限涉及到一些複雜的邏輯:檢查誰是擁有它的用戶,以及她與當前用戶的關係。它涉及更多的數據庫表。這就是爲什麼我最初認爲將該邏輯作爲模型的一部分並將計算結果返回到視圖是一個好主意...... – davidrac

相關問題