Где патчи Rails ActiveRecord :: find () для первой проверки коллекций в памяти? - PullRequest
3 голосов
/ 04 октября 2009

По несколько сложным причинам я хотел бы создать что-то, что работает так:

# 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 Ответ

1 голос
/ 05 октября 2009

Вы не должны писать то, что уже есть в самом 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

КСТАТИ. :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 объекта.

...