0

Use Case: Push my Rails 4.rc1 app to Heroku, go through asset pre-compilation, and then use asset_sync gem to put them on S3. I have the asset_host set for S3 in the config.

After this but during the slug compilation, I'd like to dump a fingerprinted asset URL to Redis so that other Heroku apps can see it (they're sharing the same Redis db) and use the same assets files. Essentially:

//s3.amazonaws.com/my_bucket/assets/desktop-(fingerprint).css

Obviously, the fingerprint changes between deploys and the other apps needs the updated URL.

Here's my first attempt:

module AssetShare
  class << self
    def capture_urls
      action_controller = ActionController::Base.new
      REDIS.set('desktop_css_url',action_controller.view_context.stylesheet_url('desktop'))
      REDIS.set('mobile_css_url',action_controller.view_context.stylesheet_url('mobile'))
    end
  end
end

desc 'Capture asset pipeline stylesheet and javascript URLS to Redis'
task 'assets:capture_urls' => :environment do
  AssetShare.capture_urls
end

# stolen from asset_sync
if Rake::Task.task_defined?("assets:precompile:nondigest")
  Rake::Task["assets:precompile:nondigest"].enhance do
    AssetShare.capture_urls
  end
else
  Rake::Task["assets:precompile"].enhance do
    AssetShare.capture_urls
  end
end

This dumped out:

//s3.amazonaws.com/my_bucket/stylesheets/desktop.css

Then I found this resource, but Sprockets has changed in Rails 4: http://blog.noizeramp.com/2011/10/14/asset-urls-and-paths-in-rake-tasks/

Here's my second attempt:

desc 'Capture asset pipeline stylesheet and javascript URLS to Redis'
task 'assets:capture_urls' => :environment do
  MyApp::Application.configure do
    config.assets.debug = false
    config.assets.digest = true
  end

  include ActionView::Helpers::AssetTagHelper

  desktop_url = stylesheet_url('desktop', only_path: false)
  REDIS.set('desktop_css_url', desktop_url)
  puts "Saved desktop url to Redis for Store Rails app: #{desktop_url}"

  mobile_url = stylesheet_url('mobile', only_path: false)
  REDIS.set('mobile_css_url', mobile_url)
  puts "Saved mobile url to Redis for Store Rails app: #{mobile_url}"
end

# stolen from asset_sync
if Rake::Task.task_defined?("assets:precompile:nondigest")
  Rake::Task["assets:precompile:nondigest"].enhance do
    Rake::Task["assets:capture_urls"].invoke
  end
else
  Rake::Task["assets:precompile"].enhance do
    Rake::Task["assets:capture_urls"].invoke
  end
end

This only dumped out:

/stylesheets/desktop.css

Obviously the first attempt it closer. I just can't get it to dump the fingerprinted url. If I run the rake task via the heroku toolkit, the correct, fingerprinted URL is printed. Thoughts?

onedanshow
  • 221
  • 3
  • 6

1 Answers1

0

Ultimately, this is the solution I had to go with:

    desc 'Capture asset pipeline stylesheet and javascript URLS to Redis'
    task 'assets:urls:capture' => :environment do

      # unfortunately, this way doesn't work when deploying
      #controller = MyApp::Application::ApplicationController.new
      #desktop_url = controller.view_context.stylesheet_url('desktop')
      #mobile_url = controller.view_context.stylesheet_url('mobile')

      desktop_url = MyApp::Application.config.action_controller.asset_host
      desktop_url += "/" + AssetSync.storage.get_remote_files.select{|d| d.include?('desktop') && d.include?('.css') }.first
      REDIS.set('desktop_css_url', desktop_url)
      puts "Saved desktop url to Redis for Store Rails app: #{desktop_url}"

      mobile_url = MyApp::Application.config.action_controller.asset_host
      mobile_url += "/" + AssetSync.storage.get_remote_files.select{|d| d.include?('mobile') && d.include?('.css') }.first
      REDIS.set('mobile_css_url', mobile_url)
      puts "Saved mobile url to Redis for Store Rails app: #{mobile_url}"
    end

    desc 'Clear asset pipeline stylesheet and javascript URLS from Redis'
    task 'assets:urls:clear' => :environment do
      REDIS.del('desktop_css_url')
      puts "Cleared desktop url from Redis"
      REDIS.del('mobile_css_url')
      puts "Cleared mobile url from Redis"
    end

    # stolen from asset_sync
    if Rake::Task.task_defined?("assets:precompile:nondigest")
      Rake::Task["assets:precompile:nondigest"].enhance do
        Rake::Task["assets:urls:capture"].invoke
        #Rake::Task["assets:urls:clear"].invoke
      end
    else
      Rake::Task["assets:precompile"].enhance do
        Rake::Task["assets:urls:capture"].invoke
        #Rake::Task["assets:urls:clear"].invoke
      end
    end

I could never get the proper fingerprinted URL to be dumped during deployment to Heroku. It says it's running as the production environment, though. This gives me a URL in Redis like:

    //s3.amazonaws.com/my_bucket/assets/desktop-6acd36e3d6c8d2b6e0fe58b83690687f.css
onedanshow
  • 221
  • 3
  • 6