I really like Textile. I think everyone does. Even if not, I like to pretend everyone does.
What I want is an easy way to turn Textile into HTML on the frontend. Rails, always the gentleman, has graciously provided us with textilize and textilize_without_paragraph helpers. That’s fine… but I want to display HTML in more places than I want to display the raw Textile markup. What if I forget to wrap my attribute in a textilize call? Isn’t there an easier way?
M@ McCray has a rendered_column plugin which will render Textile (actually, a variety of useful formats) as HTML and save it to a special rendered_* column in your database. This leaves us using something like story.rendered_description. Okay.
Thing is, I’m lazy and I don’t want to add columns to my database or do all that extra typing. I want story.description to come out as HTML unless I tell my code otherwise.
Enter: acts_as_textiled. Observe.
class Story < ActiveRecord::Base acts_as_textiled :description end >> story = Story.find(3) => #<Story:0x245fed8 ... > >> story.description => "<p>Err the <strong>Blog</strong>.</p>" >> story.description_source => "Err the *Blog*." >> story.description_plain => "Err the Blog." >> story.description = "Peter flippin' _Cooper_" => "Peter flippin' _Cooper_" >> story.description => "<p>Peter flippin’ <em>Cooper</em></p>" >> story.textiled = false => false >> story.description => "Peter flippin' _Cooper_" >> story.textiled = true => true >> story.description => "<p>Peter flippin’ <em>Cooper</em></p>"
That’s really all there is to it. Now I don’t have to wrap all my story.description calls in the textilize helper, or worry about forgetting to do so when displaying the description in new places.
But what about the create / edit form? Do I have to use story.textiled = false somewhere? Where?
No worries. Everything is handled for us.
<% form_for :story, @story do |f| %> Description: <br/> <%= f.text_field :description %> <% end %>
This will display the unrendered Textile, such as Rails _security patch_, in the textbox and work as expected. The raw Textile markup is always stored in the database.
We’re basically saying this: add the acts_as_textiled call to your model and forget about it. If you’re using form_for and no Textile helpers, everything will Just Work.
Somewhere a voice is heard crying, “But the point of saving rendered HTML to the database is efficiency. You don’t want to be parsing Textile 100 times per page!” Yes, that’s true. But it doesn’t apply to me for two reasons. First, my small apps don’t really need efficiency. acts_as_textiled uses internal caching just like ActiveRecord so if I hit the same field multiple times on a page load, the Textile is only parsed once. Second, my big apps use memcached and acts_as_textiled works great with it. The rendered HTML is cached, not the Textile itself.
I’m not saying anything against database-based implementations. Use them, they are good. But acts_as_textiled may scratch your itch.
Okay okay, give us the goods already. To install:
$ ruby script/plugin install \ svn://errtheblog.com/svn/plugins/acts_as_textiled
Check the README for other tricks you can do. Enjoy.
Update: Version 0.2 is out and hot hot hot. Thanks to James the Commenter for finding and destroying some bugs. Check the diff.