A simple Rails engine for cleanly handling Textile/Markdown markup in ActiveRecord attributes.

Using this engine, we can define a particular attribute as containing markup, with constraints around which markup rules and tags we want to support, and then render that attribute value to HTML consistently throughout the rest of the application.

Rather than adding any HTML generation into the model itself, this works by attaching metadata to the model, which can then be consumed by a helper when the attribute is used in views.

In the future, this will expand to also handle Markdown, Github-Flavoured Markdown and potentially any other markup language; the underlying mechanism is markup-agnostic, and others can easily be added.


Once you've added this gem to your application, you can enable it on a per-model basis by extending the model class with the MarkupAttributes module, and then declaring one or more attributes as having textile:

class Post < ApplicationRecord
  extend MarkupAttributes

  textile_attribute :title, :description

You can then deal with the model as with any other ActiveRecord subclass; the attributes can be treated as simple strings:

post = Post.create(title: 'My _cool_ post', description: 'A post about *stuff*')
post.title # => 'My _cool_ post'
post.description # => 'A post about *stuff*'

When you want to render the markup in a view, use the render_markup helper method:

<h1><%= render_markup post.title %></h1>
<p><%= render_markup post.description %></p>

which will produce the HTML

<h1>My <em>cool</em> post</h1>
<p>A post about <strong>stuff</strong></p>

Markup constraints

The main benefit of this gem is that it allows you to define constraints about what markup an attribute should support in a single place, and have those rules be applied consistently wherever the content is rendered. We do this using the :allow and :deny options to textile_attribute.

class Post < ApplicationRecord
  extend MarkupAttributes

  textile_attribute :title, allow: :emphasis

If any :allow options are set, anything missing from that option is assumed to be denied, and will be removed from the rendered markup. So, anywhere we try to render the title markup now, these rules will be respected:

<% post = '"Link": this _up_') %>
<%= render_markup post.title %>


Link this <em>up</em>

Because we didn't allow links, that aspect of the markup is removed.

We can include multiple allowed markup types:

textile_attribute :title, allow: [:emphasis, :links, :images]

or, we can allow all markup and then explicitly deny certain types:

textile_attribute :title, deny: :images


Add this line to your application's Gemfile:

gem 'markup_attributes'

And then execute:

$ bundle

Or install it yourself as:

$ gem install markup_attributes


Contribution directions go here.


The gem is available as open source under the terms of the MIT License.