Textilizing multiple fields at once
Textile is awesome. So awesome, in fact, that I use it on just about every text area of every Rails application I build. In the database I typically have a field for the raw text and a field for the marked-up, textilized text (one for editing, one for displaying). And up until recently I’ve only had at most one field per model that needed to be “textilized.” Well the helper I was using will no longer suffice, so I’ve implemented a new version. It’s now a class method and can accept multiple columns at once, as well as a column suffix (defaults to _html). Here’s how it works:
1 2 3 4 5 6 7 8 | # Implied DB columns: # - notes, notes_html # - description, description_html # - summary, summary_html class FilledWithText < ActiveRecord::Base textilize :notes, :description, :summary end |
However, if there is some sort of conflict or need to have the columns be something other than [column]_html, you can just pass the suffix as a key/value pair at the end of the parameter list. Also, you can give the key any name you’d like for readability sake—it only really cares about the value…
1 2 3 4 5 6 7 8 9 | # Implied DB columns: # - about, about_source # - article, article_source class MoreText < ActiveRecord::Base textilize :about, :article, :suffix => 'source' # or textilize :about, :article, :ending_of_textilized_columns => 'source' end |
It’s been quite handy for me so far. I’m sure the implementation isn’t perfect, but here’s what I came up with:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def textilize(*columns) methods = [] suffix = columns.last.is_a?(Hash) ? columns.pop.values.last : 'html' columns.each do |column| define_method "#{column}_to_html" do self["#{column}_#{suffix}"] = RedCloth.new(self[column] || '').to_html end methods << "#{column}_to_html".to_sym end before_save *methods end |
If you use textile, it’s worth doing something like this, as it makes it so much easier to convert and self-document textilized columns. Just stick it in a module to use across all of your models.
Of course, after the fact I realized there was a much better solution. I should have known to check first. Oh well, it’s still good for me to cook my own soup, so to speak.
