Как я могу вызвать обратный вызов after_save при использовании counter_cache? - PullRequest
3 голосов
/ 07 мая 2011

У меня есть модель с включенным counter_cache для ассоциации:

class Post
  belongs_to :author, :counter_cache => true
end

class Author
  has_many :posts
end

Я также использую фрагмент кэша для каждого «автора», и я хочу завершить этот кэш всякий раз, когда @author.posts_count обновляется с тех пор, какэто значение отображается в пользовательском интерфейсе.Проблема в том, что внутренние компоненты counter_cache (increment_counter и decment_counter), по-видимому, не вызывают обратные вызовы для Author, поэтому у меня нет никакого способа узнать, когда это произойдет, за исключением случаев истечения срока действия кэша из наблюдателя Post (или кэшаподметать), который просто не кажется таким чистым.

Есть идеи?

Ответы [ 5 ]

0 голосов
/ 01 февраля 2019

У меня было аналогичное требование что-то сделать при обновлении счетчика, в моем случае мне нужно было что-то сделать, если счетчик counter_cache превысил определенное значение, мое решение состояло в том, чтобы переопределить метод update_counters следующим образом:

class Post < ApplicationRecord
  belongs_to :author, :counter_cache => true
end

class Author < ApplicationRecord
  has_many :posts

  def self.update_counters(id, counters)
    author = Author.find(id)
    author.do_something! if author.posts_count + counters['posts_count'] >= some_value
    super(id, counters) # continue on with the normal update_counters flow.
  end
end

См. документация update_counters для получения дополнительной информации.

0 голосов
/ 24 января 2017

enter image description here

У меня также есть требование следить за сменой счетчика. после копания рельсов исходного кода counter_column изменяется через прямое обновление SQL. Другими словами, он не будет вызывать никакого обратного вызова (в вашем случае он не будет вызывать никакого обратного вызова в модели Author при обновлении после публикации).

из исходного кода rails, counter_column также был изменен обратным вызовом after_update.

Мой подход - дать путь рельсам, обновите counter_column самостоятельно:

class Post
  belongs_to :author
  after_update :update_author_posts_counter

  def update_author_posts_counter
    # need to update for both previous author and new author

    # find_by will not raise exception if there isn't any record
    author_was = Author.find_by(id: author_id_was) 

    if author_was
      author_was.update_posts_count!
    end
    if author
      author.update_posts_count!
    end
  end
end

class Author
  has_many :posts
  after_update :expires_cache, if: :posts_count_changed? 

  def expires_cache
    # do whatever you want
  end

  def update_posts_count!
    update(posts_count: posts.count)
  end
end
0 голосов
/ 14 июня 2011

Я закончил тем, что сохранил cache_counter как есть, но затем форсировал истечение срока действия кэша с помощью обратного вызова Post_create, как это:

class Post
  belongs_to :author, :counter_cache => true
  after_create :force_author_cache_expiry

  def force_author_cache_expiry
    author.force_cache_expiry!
  end
end

class Author
  has_many :posts

  def force_cache_expiry!
    notify :force_expire_cache
  end
end

затем force_expire_cache(author) - это метод в моем классе AuthorSweeper, который истекает фрагмент кэша.

0 голосов
/ 05 марта 2012

Что ж, у меня возникла та же проблема, и я оказался в вашем посте, но обнаружил, что, поскольку обратные вызовы "after_" и "before_" являются публичными методами, вы можете сделать следующее:

class Author < ActiveRecord::Base
  has_many :posts

  Post.after_create do
    # Do whatever you want, but...
    self.class == Post # Beware of this
  end
end

Я не знаю, насколько стандартно это сделать, но методы общедоступны, так что, думаю, все в порядке.

Если вы хотите разделить кеш и модели, вы можете использовать Sweepers .

0 голосов
/ 13 июня 2011

Я тоже не мог заставить его работать.В конце я сдался и написал свой собственный метод, похожий на cache_counter, и вызвал его из обратного вызова after_save.

...