Hey this was very interesting to watch :) Just a quick note. There is a more descriptive way to access the previous and current value of an attribute using ActiveModel::Dirty. Basically the current value is easy to get: tag_list. To get what the value was you can just call: tag_list_was. I'm pretty sure you also don't need the self. when referring to the current instance in an instance method. So:
def expire_changed_tags
modified_tags = tag_list_was - tag_list | tag_list - tag_list_was
modified_tags.each do |tag|
expire_fragment "tag/#{tag}"
end
end