После изучения DHH и других статей блога об истечении срока действия кеша и кэшировании русской куклы, я все еще не уверен, как обращаться с одним типом отношения. Конкретно, отношение has_many
.
Поделитесь результатами моих исследований с примером приложения. Это немного рассказ истории, поэтому держитесь. Скажем, у нас есть следующие модели ActiveRecord. Все, о чем мы заботимся, это правильное изменение модели cache_key
, правильно?
class Article < ActiveRecord::Base
attr_accessible :author_id, :body, :title
has_many :comments
belongs_to :author
end
class Comment < ActiveRecord::Base
attr_accessible :article_id, :author_id, :body
belongs_to :author
belongs_to :article, touch: true
end
class Author < ActiveRecord::Base
attr_accessible :name
has_many :articles
has_many :comments
end
У нас уже есть одна статья с одним комментарием. И другим автором. Цель состоит в том, чтобы изменить статью cache_key
для статьи в следующих случаях:
- Изменения в теле или названии статьи
- Изменения в тексте комментария
- Изменения имени автора статьи
- Изменения имени автора комментария комментария
Итак, по умолчанию мы хорошо применимы к случаям 1 и 2.
1.9.3-p194 :034 > article.cache_key
=> "articles/1-20130412185804"
1.9.3-p194 :035 > article.comments.first.update_attribute('body', 'First Post!')
1.9.3-p194 :038 > article.cache_key
=> "articles/1-20130412185913"
Но не для случая 3.
1.9.3-p194 :040 > article.author.update_attribute('name', 'Adam A.')
1.9.3-p194 :041 > article.cache_key
=> "articles/1-20130412185913"
Определить композитный метод cache_key
для Article
.
class Article < ActiveRecord::Base
attr_accessible :author_id, :body, :title
has_many :comments
belongs_to :author
def cache_key
[super, author.cache_key].join('/')
end
end
1.9.3-p194 :007 > article.cache_key
=> "articles/1-20130412185913/authors/1-20130412190438"
1.9.3-p194 :008 > article.author.update_attribute('name', 'Adam B.')
1.9.3-p194 :009 > article.cache_key
=> "articles/1-20130412185913/authors/1-20130412190849"
Win! Но, конечно, это не работает для случая 4.
1.9.3-p194 :012 > article.comments.first.author.update_attribute('name', 'Bernard A.')
1.9.3-p194 :013 > article.cache_key
=> "articles/1-20130412185913/authors/1-20130412190849"
Итак, какие варианты остались? Мы могли бы что-то сделать с ассоциацией has_many
на Author
, но has_many
не принимает параметр {touch: true}
и, вероятно, по какой-то причине. Я предполагаю, что это может быть реализовано несколько в следующих строках.
class Author < ActiveRecord::Base
attr_accessible :name
has_many :articles
has_many :comments
before_save do
articles.each { |record| record.touch }
comments.each { |record| record.touch }
end
end
article.comments.first.author.update_attribute('name', 'Bernard B.')
article.cache_key
=> "articles/1-20130412192036"
Пока это работает. Он оказывает огромное влияние на производительность, загружая, создавая экземпляр и обновляя каждую статью и комментируя это другим, один за другим. Я не считаю, что это правильное решение, но что такое?
Уверен, что пример использования 37signals может быть другим: project -> todolist -> todo
. Но я представляю себе один предмет todo, также принадлежащий пользователю.
Как решить эту проблему кэширования?