ProblemContributed by: Ben Bleything Your application allows users to enter content in a way that must be processed before output. You've determined that this is too slow and want to improve your application's performance by caching the result of processing the input. SolutionFirst, open the model that contains the Textile-formatted fields. Add two methods to your model to render the body when the object is saved. We're assuming that the field is called body. We'll be creating body_raw and body_rendered in a minute. class TextilizedContent < ActiveRecord::Base # your existing model code here def before_save render end private def render self.body_rendered = RedCloth.new(self.body_raw).to_html end end NOTE
We use Textile for this recipe, but the examples can easily be modified to use Markdown or other text processors. Next, create a migration to update your table schema and process all of your existing records: db/migrate/001_cache_text_processing.rb: $ script/generate migration CacheTextProcessing class CacheTextProcessing < ActiveRecord::Migration def self.up rename_column :textilized_contents, :body, :body_raw add_column :textilized_contents, :body_rendered, :text # saving the record re-renders it TextilizedContent.find(:all).each {|tc| tc.save} end def self.down rename_column :textilized_contents, :body_raw, :body remove_column :textilized_contents, :body_rendered end end The change implemented by this migration is that the database now saves both the original body, in textile format, and the rendered HTML format. Running the migration updates all existing records: $ rake db:migrate Finally, update your views to output our new body_rendered field: <%= @tc.body_rendered %> Now when someone reads a blog entry, the view returns the previously rendered content, rather than rendering it again. DiscussionConsider a blogging application. The blog author might choose to format his posts using Textile, Markdown, or some other markup language. Before you output this to a browser, it needs to be rendered to HTML. Particularly in an on-demand application like a blog, rendering content to HTML on every view can get very expensive. Caching the rendered content allows you to dramatically lessen this overhead. Instead of rendering every time the page is viewed, which slows down the reader's experience, the content is rendered only when it is created or updated. This technique can be easily modified to support multiple markup formats. Assuming you have a column in your database called markup_format, which stores the format, modify the render method in the model to use the proper renderer: def render case self.markup_format when 'html' self.body_rendered = self.body_raw when 'textile' self.body_rendered = RedCloth.new(self.body_raw).to_html when 'markdown' self.body_rendered = BlueCloth.new(self.body_raw).to_html when 'myfancyformatter' self.body_rendered = MyFancyFormatter.convert_to_html(self.body_raw) end end This caching strategy is so simple, it's debatable whether it should even be called a cache. After all, we're just using the database to store the rendered version of the blog post: we're not doing anything fancy like keeping recent posts in memory, or anything of that sort. There are other ways to alleviate the overhead of rendering content. See the other recipes in this chapter for more details. See Also
|