Mange / roadie-rails

Making HTML emails comfortable for the Rails rockstars
MIT License
367 stars 66 forks source link

Can't find asset "/stylesheets/email.css" #42

Closed rmosolgo closed 9 years ago

rmosolgo commented 9 years ago

Thanks for all your great work on this project! It's worked like a charm for the last 8 months, just hitting some issue since upgrading to Rails 4.2.

I see some issues about Rails 4.2 + "CssNotFound" regarding asset hashes, but I think I have a different problem.

Setup

I'm using:

I have a stylesheet in /app/assets/stylesheets/email.css.sass.

I have in /app/views/layouts/email.html.slim:

doctype html
html
  head
    = stylesheet_link_tag 'email'
  body

For mailers, I have ApplicationMailer:

class ApplicationMailer < ActionMailer::Base
  include Roadie::Rails::Automatic
end

then the concrete mailer:

class PeopleMailer < ApplicationMailer
  def became_administrator(person_id, new_account=false)
    # ...
    mail(
      to: @person.email_addresses.map(&:address),
      subject: "Your permissions changed!"
      )
  end
end

But I'm getting this error:

Roadie::CssNotFound in sidekiq#mailers
Could not find stylesheet "/stylesheets/email.css" 
Used provider: 
ProviderList: [ 
  #<Roadie::FilesystemProvider:0x007fe87711a640>, 
  #<Roadie::Rails::AssetPipelineProvider:0x007fe87711a190> 
]

In the console

If I open a production console, I can confirm that the stylesheet isn't found:

p = CheckIns::Application.config.roadie.asset_providers
p.map{ |p| p.class.name }
# => ["Roadie::FilesystemProvider", "Roadie::Rails::AssetPipelineProvider"]
p.map{ |p| !!p.find_stylesheet("/stylesheets/email.css") }
# => [false, false], not found
p.map{ |p| !!p.find_stylesheet("email.css") }
# => [false, true], found!

Raw Stack Trace

gems/roadie-3.0.4/lib/roadie/asset_provider.rb:8:in `find_stylesheet!': Could not find stylesheet "/stylesheets/email.css"
Used provider:
ProviderList: [
    #<Roadie::FilesystemProvider:0x007fe87711a640>,
    #<Roadie::Rails::AssetPipelineProvider:0x007fe87711a190>
] (Roadie::CssNotFound)
    from gems/roadie-3.0.4/lib/roadie/asset_scanner.rb:84:in `read_link_element'
    from gems/roadie-3.0.4/lib/roadie/asset_scanner.rb:74:in `read_stylesheet'
    from gems/roadie-3.0.4/lib/roadie/asset_scanner.rb:42:in `block in extract_css'
    from gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:187:in `block in each'
    from gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:in `upto'
    from gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:in `each'
    from gems/roadie-3.0.4/lib/roadie/asset_scanner.rb:41:in `map'
    from gems/roadie-3.0.4/lib/roadie/asset_scanner.rb:41:in `extract_css'
    from gems/roadie-3.0.4/lib/roadie/document.rb:83:in `inline'
    from gems/roadie-3.0.4/lib/roadie/document.rb:59:in `transform'
    from gems/roadie-rails-1.0.5/lib/roadie/rails/mail_inliner.rb:29:in `transform_html'
    from gems/roadie-rails-1.0.5/lib/roadie/rails/mail_inliner.rb:21:in `improve_body'
    from gems/roadie-rails-1.0.5/lib/roadie/rails/mail_inliner.rb:13:in `execute'
    from gems/roadie-rails-1.0.5/lib/roadie/rails/inline_on_delivery.rb:11:in `deliver'
    from gems/actionmailer-4.2.1/lib/action_mailer/message_delivery.rb:85:in `deliver_now'
    from gems/actionmailer-4.2.1/lib/action_mailer/delivery_job.rb:10:in `perform'
    from gems/activejob-4.2.1/lib/active_job/execution.rb:32:in `block in perform_now'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:498:in `block (2 levels) in around'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:343:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:343:in `block (2 levels) in simple'
    from gems/newrelic_rpm-3.12.0.288/lib/new_relic/agent/instrumentation/active_job.rb:46:in `call'
    from gems/newrelic_rpm-3.12.0.288/lib/new_relic/agent/instrumentation/active_job.rb:46:in `perform'
    from gems/newrelic_rpm-3.12.0.288/lib/new_relic/agent/instrumentation/active_job.rb:20:in `block (3 levels) in <top (required)>'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:441:in `instance_exec'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:441:in `block in make_lambda'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:342:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:342:in `block in simple'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:497:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:497:in `block in around'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:498:in `block (2 levels) in around'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:343:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:343:in `block (2 levels) in simple'
    from gems/activejob-4.2.1/lib/active_job/logging.rb:23:in `call'
    from gems/activejob-4.2.1/lib/active_job/logging.rb:23:in `block (4 levels) in <module:Logging>'
    from gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `block in instrument'
    from gems/activesupport-4.2.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `instrument'
    from gems/activejob-4.2.1/lib/active_job/logging.rb:22:in `block (3 levels) in <module:Logging>'
    from gems/activejob-4.2.1/lib/active_job/logging.rb:45:in `tag_logger'
    from gems/activejob-4.2.1/lib/active_job/logging.rb:19:in `block (2 levels) in <module:Logging>'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:441:in `instance_exec'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:441:in `block in make_lambda'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:342:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:342:in `block in simple'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:497:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:497:in `block in around'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_perform_callbacks'
    from gems/activesupport-4.2.1/lib/active_support/callbacks.rb:81:in `run_callbacks'
    from gems/activejob-4.2.1/lib/active_job/execution.rb:31:in `perform_now'
    from gems/activejob-4.2.1/lib/active_job/execution.rb:21:in `execute'
    from gems/activejob-4.2.1/lib/active_job/queue_adapters/sidekiq_adapter.rb:40:in `perform'
    from gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:75:in `execute_job'
    from gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:52:in `block (2 levels) in process'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:127:in `call'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:127:in `block in invoke'
    from gems/newrelic_rpm-3.12.0.288/lib/new_relic/agent/instrumentation/sidekiq.rb:33:in `block in call'
    from gems/newrelic_rpm-3.12.0.288/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:352:in `perform_action_with_newrelic_trace'
    from gems/newrelic_rpm-3.12.0.288/lib/new_relic/agent/instrumentation/sidekiq.rb:29:in `call'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
    from gems/sidekiq-pro-1.9.2/lib/sidekiq/batch/middleware.rb:26:in `call'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/server/active_record.rb:6:in `call'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/server/retry_jobs.rb:74:in `call'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/server/logging.rb:11:in `block in call'
    from gems/sidekiq-3.3.0/lib/sidekiq/logging.rb:22:in `with_context'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/server/logging.rb:7:in `call'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:132:in `call'
    from gems/sidekiq-3.3.0/lib/sidekiq/middleware/chain.rb:132:in `invoke'
    from gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:51:in `block in process'
    from gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:98:in `stats'
    from gems/sidekiq-3.3.0/lib/sidekiq/processor.rb:50:in `process'
    from gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
    from gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
    from gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
    from gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
    from gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
    from gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
    from gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
    from gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'

??

Do you have any suggestions on how I can find out more info? I'm not sure where to look next!

Thanks for you help!

Mange commented 9 years ago

Thank you for an excellent issue report.

Are you precompiling your assets in production? Your view doesn't seem to pick up on this fact. Maybe you haven't run the precompilation on the machine that handles your background jobs?

Your asset URL also seem to be non-standard. The filesystem provider automatically tries to remove /assets before looking, but I only see /stylesheet here, so either it's stripping "assets" and reports the result, or you don't keep your assets under a directory called "assets".

You could try to manually add a new filesystem provider with a prefix that matches your case (See documentation for the method signatures). Does that work like it should?

rmosolgo commented 9 years ago

Thanks for your response.

Maybe you haven't run the precompilation on the machine that handles your background jobs?

This might be true (investigation below), I'm checking now how our other apps handle this situation.

Precompiled?

This file should be precompiled:

    config.assets.precompile += [
      "email.css",
      # ...
     ]

And it seems like it is precompoiled. We have a mail preview on Production that uses the correct URL:

image

However, in a Rails console, the stylesheet_link_tag comes out "wrong":

include ActionView::Helpers::AssetTagHelper
stylesheet_link_tag("email")
# => "<link rel=\"stylesheet\" media=\"screen\" href=\"/stylesheets/email.css\" />"

It's gotta be something to do with the environment ... hummm... !

rmosolgo commented 9 years ago

Also, it's clear that the file is really there:

$ ls public/assets | grep email
email-d50d5813662811a4dc75aadc1fdc11e6.css
email-d50d5813662811a4dc75aadc1fdc11e6.css.gz
rmosolgo commented 9 years ago

Solution

Just make the stylesheet_link_tag by hand:

doctype html
html
  head
    link rel='stylesheet' type='text/css' href='/assets/email.css'

I saw that our other apps do this (for some other CSS inlining gem) and it was a workaround on this issue

I wish I could have found the "real" issue, sure seems like something about my environment ... but I have to get this show on the road!

Thanks again for your help and for your work on this project!