[typo] Towards fragment tracking

Piers Cawley pdcawley at bofh.org.uk
Tue Oct 11 02:37:33 EDT 2005


Talking with slaird on IRC I volunteered to write up some design notes for the
list on my ideas about how to do cache tracking.

At present, whenever anything changes in the database, we simply zap everything
in the cache. This is, um, inefficient...

What we need is a mapping between our cached views/fragments and the models
that contribute to them. How do we arrange things?

Here's a proposal:

We extend the Content class so that all attributes declared with
'content_fields' can take an optional argument, :controller. The basic accessor
method would look like:

  def body(controller=NullController.instance)
    controller.depends_on(self)
    self[:body]
  end

We also declare a new relationship:

  Content.has_and_belongs_to_many :dependents, :class => FragmentPath

Meanwhile, the controller keeps track of the fragment path that's currently
being rendered (or possibly, if we're caching nested fragments, the list of
fragments we're currently rendering) and defines 

  def depends_on(content)
    if current_fragment
      content.add_dependent(current_fragment)
    end
  end

Now, assuming we capture all the appropriate content attributes (more than just
body and extended) we have a nice, reliable mapping between content objects and
html fragments, so our cache sweeper can look something like:

  class ContentSweeper < ActionController::Caching::Sweeper
    def after_save(content)
      expire_dependents(content)
    end

    def after_destroy(content)
      expire_dependents(content)
    end

    private

    def expire_dependents(content)
      content.dependents.each do |fragment|
        expire_fragment fragment.to_s
        fragment.destroy
      end
    end
  end

But what about when comments get added? How do we handle that? I hear you ask.
Easy, we do what we should have been doing for a while now:

  Comment.belongs_to :article, :counter_cache => true
  Trackback.belongs_to :article, :counter_cache => true

and add comment_count and trackback_count columns to the contents table. Now,
whenever we add a comment, the article itself gets saved and, as if by magic,
the appropriate cached fragments get flushed.

Note that there's been a certain amount of handwaving about precisely how the
controller tracks the current fragment, but that implementation detail doesn't
really affect how we make this work.

So, comments? Questions? Corrections?

-- 
Piers Cawley <pdcawley at bofh.org.uk>
http://www.bofh.org.uk/


More information about the Typo-list mailing list