jcasimir/draper — Issue #136: Custom helpers not available to decorators instantiated in a mailer
Author: ramontayag
Created: 2012-03-03 03:47:11+00:00
State: open

I have an issue where it seems that custom helpers (Rails helpers are) aren't accessible by decorators instantiated in mailers. Here's how to reproduce the bug:

rails new draper_mailer_helper
cd draper_mailer_helper

Add to Gemfile:

gem 'draper'

Install draper:

bundle install
rails g draper:install

Make a dummy model:

rails g model Product price_cents:integer
rake db:migrate

Create decorator for Product `app/decorators/product_decorator.rb`

class ProductDecorator < ApplicationDecorator
decorates :product

def price
h.number_to_php price_cents.to_f/100
end
end

Create custom helper `app/helpers/custom_helper.rb`:

class CustomHelper
def number_to_php(n)
number_to_currency n, :unit => 'P'
end
end

Create our mailer `app/helpers/mailer.rb`:

class Mailer < ActionMailer::Base
default_url_options[:host] = 'fakehost.com'

def purchase_notice(product_id)
set_current_view_context
@product_decorator = ProductDecorator.decorate Product.find(product_id)
mail :subject => 'You bought a product', :to => 'test@email.com', :from => 'admin@email.com'
end
end

Create the view `app/views/mailer/purchase_notice.html.erb`:

You got a product for <%= @product_decorator.price %>!

Test the mailer

rails c
p = Product.create :price_cents => 1000
Mailer.purchase_notice(p.id).deliver

You'll get an error like:

ActionView::Template::Error: ActionView::Template::Error
from /home/ramon/src/draper_mailer_helper/app/decorators/product_decorator.rb:5:in `price'
from /home/ramon/src/draper_mailer_helper/app/views/mailer/purchase_notice.html.erb:1:in `_app_views_mailer_purchase_notice_html_erb___629649561_88432090'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/template.rb:171:in `send'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/template.rb:171:in `render'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/activesupport-3.1.3/lib/active_support/notifications.rb:55:in `instrument'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/template.rb:169:in `render'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/renderer/template_renderer.rb:40:in `render_template'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/renderer/abstract_renderer.rb:33:in `instrument'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/activesupport-3.1.3/lib/active_support/notifications.rb:53:in `instrument'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/activesupport-3.1.3/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/activesupport-3.1.3/lib/active_support/notifications.rb:53:in `instrument'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/renderer/abstract_renderer.rb:33:in `instrument'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/renderer/template_renderer.rb:39:in `render_template'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/renderer/template_renderer.rb:47:in `render_with_layout'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/renderer/template_renderer.rb:38:in `render_template'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/action_view/renderer/template_renderer.rb:12:in `render'
... 7 levels...
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:718:in `collect_responses_and_parts_order'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:729:in `each'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:729:in `each_template'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:714:in `collect_responses_and_parts_order'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:653:in `mail'
from /home/ramon/src/draper_mailer_helper/app/models/mailer.rb:7:in `purchase_notice'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/abstract_controller/base.rb:167:in `send_action'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/abstract_controller/base.rb:167:in `process_action'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/abstract_controller/base.rb:121:in `process'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionpack-3.1.3/lib/abstract_controller/rendering.rb:45:in `process'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/old_api.rb:65:in `process'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:474:in `process'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:469:in `initialize'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:456:in `new'
from /home/ramon/.rvm/gems/ree-1.8.7-2011.03/gems/actionmailer-3.1.3/lib/action_mailer/base.rb:456:in `method_missing'

If you change `number_to_php` to a Rails helper like `number_to_currency`, it'll work. This tells me the custom helpers we create aren't available to stuff decorated in a mailer. I poked around a bit and found the [all_helpers](http://rubydoc.info/github/jcasimir/draper/master/Draper/AllHelpers#all_helpers-instance_method) method, and can see the code that attempts to load application helpers. Don't know enough about Draper to figure out why this doesn't work though.