By Kayla Morrison September 25, 2014

How to create a Markdown-friendly blog in a Rails app

When making my new portfolio, I wanted to include a simple blog. My requirements were that I be able to 1) write my posts in Markdown and 2) put the three most recent posts on the home page. Simple, right? Nope. This took me forever to figure out.

Attempt #1

At first, I was just going to have a blog model/view/controller that I managed through RailsAdmin, but I quickly realized that was going to give me a huge block of text with no formatting whatsoever, which wasn’t going to work in a code-heavy blog.

Attempt #2

Then, I thought that I could integrate a Jekyll blog into my existing app. There is a gem for this called bloggy that works really well, but I ran into a problem when I wanted to display posts on the front page. Jekyll uses Liquid as a templating language, and I was using Rails’ out-of-the-box ERB. As far as I can tell, there is no way to make those two play nicely together.

If I were starting from scratch, I might have tried switching my entire app over to Liquid because it’s pretty neat. It’s extracted from Shopify and is primary use is for situations where you want to allow users control over their layout in a Rails app, but don’t want to let them run amok with Ruby on your server. Making things user-editable like this has become an interest of mine while I’ve been doing some freelance work for a friend who does custom Squarespace sites (yes, there is a huge market for this even though Squarespace is designed so that “anyone” can use it). But in this case, I already had all my views laid out in ERB. It would have taken a long time to switch, so I eliminated that option.

Attempt #3

Then I thought that maybe I could find something similar to Jekyll that uses ERB. There are several options: <a href=“http://middlemanapp.com/” “target=”_blank">Middleman, Frank, Nanoc, etc., but none of them could be easily integrated into an existing Rails app the way that Jekyll could with bloggy.

The solution

Finally, I stepped back and realized that there was probably a way to go with my original tactic and parse my Markdown blog posts into HTML. That’s when I found Redcarpet, which was developed at GitHub and does exactly what I needed.

I started off with this Railscast on it, but it’s pretty outdated, so I had to consult the docs to get things working correctly. Here’s my final solution:

I added two gems to my Gemfile:

gem 'redcarpet'
gem 'coderay'

More on CodeRay in a minute.

Next, I created a helper method for Redcarpet in app/helpers/application_helper.rb:

 markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
    no_intra_emphasis: true, 
    fenced_code_blocks: true,   
    disable_indented_code_blocks: true)
return markdown.render(text).html_safe
end

Now in my view, I can do this:

<%= markdown(@blog.body) %> 

and it will convert my markdown into HTML automatically.

Including code and syntax highlighting

That works fine if you’re just writing a blog about your cat or something, but if you are writing a blog about Rails development you’re going to have a lot of code. If you don’t care about syntax highlighting and just want your code to be differentiated from your explanations, somehow you could just fiddle with the CSS and be done with it, but I thought that it would be nice to have some syntax highlighting as well.

In the Railscast, Ryan Bates uses a now-deprecated gem called Abino, which is a Ruby wrapper for Python’s Pygmentize. Pygments.rb is essentially the same thing, but it requires Python, and I didn’t want to deal with getting Python running on my machine. After some searching, I found CodeRay, which is written in Ruby. The documentation on CodeRay is lacking, but, luckily, I found this blog post and pretty much copied the code within. Now my helper looks like this:

module ApplicationHelper
class CodeRayify < Redcarpet::Render::HTML
  def block_code(code, language)
    CodeRay.scan(code, language).div
  end
end

def markdown(text)
  coderayified = CodeRayify.new(:filter_html => true, 
                                :hard_wrap => true)
  options = {
    :fenced_code_blocks => true,
    :no_intra_emphasis => true,
    :autolink => true,
    :lax_html_blocks => true,
  }
  markdown_to_html = Redcarpet::Markdown.new(coderayified, options)
  markdown_to_html.render(text).html_safe
end
end

If you’re curious about what is going on in that options hash, Redcarpet has very good documentation, which explains what all of the options do and lists some others I didn’t use.

One additional caveat with using CodeRay is that you have to use fenced code blocks and identify the language you are using, instead of just indenting.

There you go, a Markdown-friendly blog inside your Rails app, minus the entire day of Googling required to get there.

P.S.

If you’re like me and always forget Markdown syntax, might I recommend MacDown. It shows you what your text will look like once it’s converted to HTML. I was using Mou, but apparently that is not in development anymore, and it doesn’t support fenced code blocks. Macdown does and (for now, at least) is being actively developed.