My production asset_host config looks like this:
config.action_controller.asset_host = Proc.new { |source, request|
if request.ssl?
"#{request.protocol}#{request.host_with_port}"
else
"#{request.protocol}assets#{(source.length % 4) + 1}.example.com"
end
}
...which is more or less straight from the docs:
http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html
When I go to assets:precompile, I get this:
$ RAILS_ENV=production bundle exec rake assets:precompile
rake aborted!
This asset host cannot be computed without a request in scope. Remove
the second argument to your asset_host Proc if you do not need the
request.
....except that I can't really remove the 2nd arg because I need to know if the request is ssl or not. That said, I understand that a request isn't present during the rake task to generate the assets....
So how do I get out of this catch 22?
To compile your assets locally, run the assets:precompile task locally on your app. Make sure to use the production environment so that the production version of your assets are generated. A public/assets directory will be created. Inside this directory you'll find a manifest.
rake assets:clean Only removes old assets (keeps the most recent 3 copies) from public/assets . Useful when doing rolling deploys that may still be serving old assets while the new ones are being compiled.
rails assets:precompile is the task that does the compilation (concatenation, minification, and preprocessing). When the task is run, Rails first looks at the files in the config.assets.precompile array. By default, this array includes application.js and application.css .
This will happen when (1) your assets use paths, for example:
background:url(image_path('awesome-background.gif'))
and (2) your asset_host
is set to a lambda/proc that requires the second argument (request
).
Your options are to either remove the request
argument (if you don't actually use it) or make it optional (and handle the case where it is nil
). This is easy in Ruby 1.9 (and should be easier, see notes):
config.action_controller.asset_host = ->(source, request = nil, *_){
# ... just be careful that request can be nil
}
If you want to be compatible with Ruby 1.8, there is no direct way to create a Proc/lambda with parameters with defaults, but you can use:
config.action_controller.asset_host = Proc.new do |*args|
source, request = args
# ...
end
Or do it using a method:
def MyApp.compute_asset_host(source, request = nil)
# ...
end
config.action_controller.asset_host = MyApp.method(:compute_asset_host)
Notes:
nil
to signify the "default host", no need to use "#{request.protocol}#{request.host_with_port}"
//
should use the default protocol (http or https). I'm saying "should" as it looks like IE <= 8 will download the css assets twice and I've ran into problems with PDFkit.So in your particular case, your asset_host
can be simplified to:
config.action_controller.asset_host = Proc.new { |source, request = nil, *_|
"//assets#{(source.length % 4) + 1}.example.com" if request && !request.ssl?
}
Edit: Use a lambda or else the *_
to avoid a bug feature of Ruby.
For ruby 1.8.x, @Marc-Andre's method(:compute_asset_host)
technique didn't work for me. Even though the method was defined directly above, NameError: undefined method `compute_asset_host' for class `Object'
was raised.
Here's what worked for me:
config.action_controller.asset_host = Proc.new do |*args|
source, request = args
if request.try(:ssl?)
'ssl.cdn.mysite.com'
else
'cdn%d.mysite.com' % (source.hash % 4)
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With