technicalpickles

Open Source ProjectsCode that Might be Useful to You

Talks I've GivenOn Technologies and Ideas

ThoughtsWhere I Sometimes Write Things

Resume If You Believe In Those

Follow Me On

GitHubIf coding is your thing

TwitterIf you tweet

Manage your markup with has_markup


I recently decided to extract some plugins, in an effort to clean up the codebase for my blog.

The first thing I tackled was generation of HTML from my Post model.

In the beginning…

Here’s the starting point for my model:

class Post < ActiveRecord::Base
  # --- SNIP ---

  # TODO move into own file... and plugin?
  def self.validates_markdown(*attrs)
    validates_each(*attrs) do |record, attr, value|
      begin
        BlueCloth.new(value).to_html unless value.nil?
      rescue BlueCloth::FormatError => e
        errors.add attr, "has #{e}"
      end
    end
  end
  validates_presence_of :content
  validates_markdown :content
  before_save :cache_content

  # Use BlueCloth to generate HTML ahead of time.
  def cache_content
    html = BlueCloth.new(self.content).to_html
    self.cached_content = html
  end

  # --- SNIP ---
end

validates_markdown really doesn’t belong here, and nothing interesting is happening, but the lines of code start to add up.

Let’s look at the partial for Post.

%div{ :id => dom_id(post), :class => dom_class(post) }
  %h2.title= link_to(post.title, post)
  .content~ post.cached_content

Eh, nothing particuarly interesting.

Goals

  • One-liner for specifying markup, similar to has_many or acts_as_taggable
  • Optionally require the markup
  • Optionally cache the markup
  • Allow for different syntaxes

A whole new look on things

I was able to extract the logic out of my model and hit all of these goals.

The refactored model:

class Post < ActiveRecord::Base
  # --- SNIP ---

  has_markup :content, :required => true, :cache_html => true

  # --- SNIP ---
end

And the view is more or less the same:

%div{ :id => dom_id(post), :class => dom_class(post) }
  %h2.title= link_to(post.title, post)
  .content~ post.cached_content_html

Thoughts

  • Plugins are really easy to make
  • Plugins can pull a good amount of code out of your model, which results in it being more readable
  • I think I finally understand the difference between include and extend

Get it

If you’re interested in trying this plugin, it is hosted on GitHub. You can install it by with:

script/plugin install git://github.com/technicalpickles/has_markup.git 
comments powered by Disqus