Where to fix Rails ActiveRecord :: find () to check collections in memory first?

For rather complex reasons, I would like to create something that works like this:

# 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 no way for find() to realize that :(
comment.children

      

I'm not even sure if it's possible, let alone a good idea, but I'm curious and would be helpful.

Basically I want to redirect find () so that it looks first / only in an already loaded collection, using something like hypothetical @collection.find{|item| item.matches_finder_sql(...)}

.

The point is to prevent unnecessary complex caching and expensive database lookups for things that have already been loaded in droves.

If possible it would be nice if it played well with existing mechanisms for stability, lazy loading pooling, etc.

The nested comments are just an example; of course, this applies to many other situations as well.

So ... how could I do this?

+2


source to share


1 answer


You don't have to write what's already in Rails! You can easily use Rails' caching methods to post query results to Memcached (or whatever cache configuration):

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

is optional. You can keep the cache "forever" or fix it manually.



Second example, as per my comment:

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

      

This will cache articles and comments for the given object @page

.

+1


source







All Articles