Sunday, December 5, 2010

Providing markdown engine options in HAML

I've started looking into using Markdown in Rails. I use HAML for rendering views, so markdown is handled by a HAML filter:

  1. %h1 Here's some rendered Markdown  
  2.   :markdown  
  3.     = @model.markdown  

This worked great, but I was concerned about javascript injection since the markdown would be provided by a user using a WMD editor. I found that I could explicitly call RDiscount, with the :filter_html option, to render the markdown myself:

  1. %h1 Here's some rendered Markdown  
  2.   != RDiscount.new(@model.markdown, :filter_html).to_html  

This worked great, but I didn't want to have to remember this incantation every time I want to render some Markdown. After some discussion with Nathan Weizenbaum the current maintainer of Haml, I realized that the answer is actually presented (somewhat indirectly) through the documentation. The section on Custom Filters says "You can also define your own filters. See Haml::Filters for details.". You have to then follow on to Haml::Filters::Base for the full story.

In my Rails app, I created a custom Haml filter that overrides the original :markdown (so I don't accidentally forget and use an unsafe :markdown) config/initializers/haml.rb:

  1. module MyApp  
  2.   module Filters  
  3.     module Markdown  
  4.       include Haml::Filters::Base  
  5.       lazy_require 'rdiscount'  
  6.   
  7.       def render(text)  
  8.         ::RDiscount.new(text, :filter_html).to_html  
  9.       end  
  10.     end  
  11.   end  
  12. end  

Now, whenever HAML renders a :markdown filter, it will filter the HTML and protect me against javascript injection attacks.

Thursday, December 2, 2010

Stop deploying unneccessary Gems in your Heroku slug

Heroku published a handy tip in their newsletter today:
$ heroku config:add BUNDLE_WITHOUT=development:test
Having set this and pushed a change to my Gemfile, my slug size went from 39.4MB down to 10.9MB.

Smaller slugs compile and load faster.

Thank you Heroku!

Monday, November 22, 2010

Rake duplicate task descriptions

Using Rake I can define tasks that get added to a collection of tasks for execution.  For example:
  1. desc "one"  
  2. task :one do  
  3.   puts "one"  
  4. end  
  5.   
  6. desc "all"  
  7. task :all => [:one]  
  8.   
  9. desc "two"  
  10. task :two do  
  11.   puts "two"  
  12. end  
  13.   
  14. desc "all"  
  15. task :all => [:two]  

Now, if I look at rake --tasks I will see:
> rake --tasks
rake one     # one
rake two     # two
rake all     # all / all

Rake has duplicated the description for the :all task. Looking at the code for Rake I discovered that this can be avoided by terminating the :all task description with a period:
  1. desc "one"  
  2. desc "all."  
  3. task :all => [:one]  
  4.   
  5. desc "one"  
  6. desc "all."  
  7. task :all => [:one]  

> rake --tasks
rake one     # one
rake two     # two
rake all     # all.