При написании статей уже давно не принято использовать простую HTML-разметку. Набирать каждый раз HTML-теги вручную — не самое приятное времяпрепровождение. Зачастую для этих целей используются user-friendly редакторы а-ля TinyMCE. И выглядят неплохо, и справиться с ними в силах любой необременённый излишками знания пользователь. Минус один: html-разметка, получаемая на выходе, может совсем не радовать глаз автора и мохнатые лапки поисковых «пауков».
По другую сторону сто́ят облегчённые языки разметки, самым популярным из которых является markdown. Вот его-то мы и будем подключать к Rails-проекту.
Для начала установим необходимые гемы. Для этого их следует прописать в Gemfile:
# Gemfile
gem 'redcarpet', '~> 3.0.0'
gem 'pygments.rb'И дать команду:
$ bundle installПосле чего обратимся к созданию helper'а, призванного сгенерировать html из
файла с разметкой markdown. За генерацию страниц в html из markdown в
ответе redcarpet. К тому же благодаря pygments.rb у нас появляется
возможность подсветки синтаксиса в коде.
# helpers/application_helper.rb
module ApplicationHelper
  class HTMLwithPygments < Redcarpet::Render::HTML
    require 'pygments.rb'
    def block_code(code, language)
      Pygments.highlight(code, :lexer => language)
    end
  end
  def markdown(text, options = {})
    renderer = HTMLwithPygments.new(hard_wrap: true)
    options={
      autolink: true,
      no_intra_emphasis: true,
      fenced_code_blocks: true,
      lax_html_blocks: true,
      strikethrough: true,
      superscript: true,
      space_after_headers: true,
      underline: true,
      highlight: true,
      quote: true
    }
    Redcarpet::Markdown.new(renderer, options).render(text).html_safe
  end
endДля подсветки синтаксиса нужно написать блок кода и указать необходимый ЯП, вот так:
~~~ruby
puts "Hello!"
~~~Функция markdown принимает на вход текст с указанными опциями и генерирует html-страницу. Подробно об имеющихся опциях и их значении можно прочесть на странице проекта.
Осталось лишь вывести наш текст на обозрение массам:
<%# posts/show.html.erb %>
<%= link_to @post.title, post_path(@post) %>
  <%= markdown @post.content %>С этим способом в базе данных текст хранится в формате markdown, а перед тем,
как страница будет отображена, redcarpet переводит её в html-формат.
С точки зрения производительности не самый лучший вариант.
Но есть и другой способ: сгенерировать html перед тем, как сохранять файл
в базу данных при помощи before_save.
# post.rb
#
# Table name: posts
#
#  id         :integer     not null, primary key
#  title      :string(255)
#  content    :text
#  slug       :string(255)
#  summary    :string(255)
#  created_at :datetime
#  updated_at :datetime
class Post < ActiveRecord::Base
  before_save :render_content
  def render_content
    require 'redcarpet'
    renderer = HTMLwithPygments
    extensions = {fenced_code_blocks: true}
    redcarpet = Redcarpet::Markdown.new(renderer, extensions)
    self.content = redcarpet.render self.content
  end
  class HTMLwithPygments < Redcarpet::Render::HTML
    require 'pygments.rb'
    def block_code(code, language)
      Pygments.highlight(code, :lexer => language)
    end
  end
endЕсли ресурс не относится к техническим и статья не предназначена для
вывода блоков кода можно обойтись без pygments:
# post.rb
class Post < ActiveRecord::Base
  before_save :render_content
  def render_content
    require 'redcarpet'
    renderer = Redcarpet::Render::HTML.new
    extensions = {fenced_code_blocks: true}
    redcarpet = Redcarpet::Markdown.new(renderer, extensions)
    self.content = redcarpet.render self.content
  end
endТеперь в базе будет лежать готовая html-страница.
Для корректного вывода такой странички нам нужно использовать
стандартный фильтр html_safe:
<%# posts/show.html.erb %>
<%= link_to @post.title, post_path(@post) %>
  <%= @post.content.html_safe %>Ещё раз: в первом примере (при генерации «на лету») страница
сохраняется в формате markdown, каждый раз перед тем как вывести её
содержимое redcarpet генерирует текст из markdown в html.
Во втором примере отображается предварительно сгенерированный html-код. Так что вы вольны выбирать, какой из вариантов удобнее в каждом конкретном случае.