Fragment Caching

#24 Fragment Caching
4/14/2016

Summary

Make your application faster by leveraging memory and caching fragments of your view.
4
rails caching performance 7:70 min

Summary


development.rb    config.action_controller.perform_caching = true
    config.cache_store = :dalli_store, 'localhost'
_story.html.erb
    <% cache story do %>
      <%= content_tag :li, class: 'list-group-item' do %>
        <h5><%= story.name %></h5>
        <p><%=h raw story.content %></p>
        <div class='row'>
          <div class='col-xs-8'>
            <% story.tag_list.each do |tag| %>
              <%= content_tag :span, tag, class: 'label label-primary' %>
            <% end %>
            <%= link_to 'Edit', edit_story_path(story), class: 'label label-info' %>
          </div>
          <div class='col-xs-4'>
            <div class='pull-right'><em>created <%= time_ago_in_words story.created_at %></em></div>
          </div>
        </div>
      <% end %>
      <% sleep 0.1 # Crazy Long Running Process %>
    <% end %>
stories/index.html.erb
    <% @most_tagged.each do |tag| %>
      <% cache ['tag', tag.try(:name)], skip_digest: true do %>
        <li class='list-group-item'><%= "#{tag.try(:name).try(:titleize)} (#{tag.taggings_count})" %></li>
      <% end %>
    <% end %>
config/initializers/active_record_base.rb
    class ActiveRecord::Base
      def expire_fragment(*args)
        ActionController::Base.new.expire_fragment(*args)
      end
    end

Update:  Thank you /u/danshep for pointing this out.

https://www.reddit.com/r/ruby/comments/4epmeb/tutorial_fragment_caching/d22bjzl

model/story.rb
    # before_update :expire_changed_tags, if: :tag_list_changed?
    before_save :expire_changed_tags, if: :tag_list_changed?
    private
    def expire_changed_tags
      original_tag_list = self.tag_list_change.first
      new_tag_list = self.tag_list_change.last
      modified_tags = original_tag_list - new_tag_list | new_tag_list - original_tag_list
      modified_tags.each do |tag|
        self.expire_fragment "tag/#{tag}"
      end
    end
635114?v=3&s=64
kobaltz said over 1 year ago:

Check out the show notes for an update to the code. Thank you /u/danshep for pointing this out. https://www.reddit.com/r/ruby/...

81871?v=3&s=64
brendon said over 1 year ago:

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

635114?v=3&s=64
kobaltz said over 1 year ago:

You are absolutely correct. In the tutorials, I do like indicating self` as it is more clear where we are calling the methods from instead of a separate helper or extension outside of the model we're working with. For anyone who wants to see the available options for ActiveRecord::Dirty be sure to read up on them here http://api.rubyonrails.org/cla....

901101?v=3&s=64
mabel said over 1 year ago:

Really very good job. Thank you!

Login to Comment