2009-10-04 25 views
2

对于比较复杂的原因,我想创造的东西,是这样的:在哪里补丁Rails ActiveRecord :: find()首先检查内存中的集合?

# Controller: 
@comments = @page.comments # comments are threaded 
# child comments still belong to @page 
... 
# View: 

@comments.each_root { 
    display @comment { 
    indent & recurse on @comment.children 
} } 

# alternatives for how recursion call might work:  

# first searches @comments, then actually goes to SQL 
comment.in_memory.children 

# only looks at @comments, RecordNotFound if not there 
# better if we know @comments is complete, and checking for nonexistent 
# records would be wasteful 
comment.in_memory(:only).children 

# the real thing - goes all the way to DB even though target is already in RAM 
# ... but there's no way for find() to realize that :(
comment.children 

我什至不知道但如果这是可能的,更何况是一个好主意,但我很好奇,和这会有所帮助。

基本上我想重定向find(),以便它首先看到/只在已经加载的集合上,使用类似假设的@collection.find{|item| item.matches_finder_sql(...)}

重点是防止不必要的复杂缓存和昂贵的数据库查找的东西,已被加载整体。

如果可能的话,这将会是好的,如果这个打了现存机制陈旧,关联延迟加载等

的嵌套评论的事情仅仅是一个很好的例子;当然这也适用于很多其他情况。

那么......我该怎么做?

回答

1

你不应该写一些已经在Rails中的东西!您可以轻松地利用Rails的高速缓存方法把你的查询结果Memcached的(或什么都缓存框架已配置):

class ArticleController < ApplicationController 
    def index 
    @articles = Rails.cache(:articles_with_comments, :expires_in => 30.minutes) do 
     Article.find(:all, :include => :comments) 
    end 
    end 
end 

BTW。 :expires_in是可选的。您可以永久保留缓存或手动将其终止。

第二个例子,正如我的评论:

class ArticleController < ApplicationController 
    def index 
    @page = Page.find(params[:page_id] 

    @articles = Rails.cache([:articles_with_comments, @page.id], :expires_in => 30.minutes) do 
     Article.find(:all, :include => :comments, :conditions => { :page_id => @page.id}) 
    end 
    end 
end 

这将缓存对于给定@page对象的文章和评论。

+0

作为额外的好处,您可以使用缓存键的数组。这个键可能包含'动态'变量。我添加了第二个例子。 – Ariejan 2009-10-04 20:03:52

+0

这不会做我想做的事,因为它不允许我继续使用标准的查找和查找使用方法(如来自awesome_nested_set的.children)。问题不是缓存问题(比如你的问题),而是更多的代理问题。 – Sai 2009-10-10 06:29:05