Rails asset pipeline and digest values
Grabbed from rails guides
When a filename is unique and based on its content, HTTP headers can
be set to encourage caches everywhere (whether at CDNs, at ISPs, in
networking equipment, or in web browsers) to keep their own copy of
the content. When the content is updated, the fingerprint will change.
This will cause the remote clients to request a new copy of the
content. This is generally known as cache busting.The technique that Rails uses for fingerprinting is to insert a hash
of the content into the name, usually at the end. For example a CSS
file global.css could be renamed with an MD5 digest of its contents
How can I determine the MD5 digest of a given asset in the Rails asset pipeline?
As someone mentioned in the comments, appending a hash to the asset paths is a default part of the asset pipeline.
You can read more about fingerprinting in the asset pipeline here. Rails uses Sprockets to compile assets. The fingerprinting comes as part of Sprockets process.In production, Rails inserts an MD5 fingerprint into each filename so that the file is cached by the web browser
You can use Sprockets' find_asset
method, passing in a logical path to your asset to get a Sprockets::BundledAsset
instance. For example
[1] pry(main)> Rails.application.assets.find_asset('application.js')
=> #<Sprockets::BundledAsset:0x3fe368ab8070 pathname="/Users/deefour/Sites/MyApp/app/assets/javascripts/application.js", mtime=2013-02-03 15:33:57 -0500, digest="ab07585c8c7b5329878b1c51ed68831e">
You can call digest_path
on this object to get it's MD5
sum appended to the asset.[1] pry(main)> Rails.application.assets.find_asset('application.js').digest_path
=> "application-ab07585c8c7b5329878b1c51ed68831e.js"
With this knowledge you can easily create a helper to return the digest_path
for any asset in your application, and call this helper from within your .js.erb
files. Rails: How do I force a new asset digest on ALL assets?
I found the only way to force expiration of assets and get them recompiled was to add the following in my config/environments/production.rb
config.assets.version = '1.1' #This currently doesnt work as intended so use
config.assets.prefix = '/production'
Then bundle exec rake assets:precompile RAILS_ENV=production
Rails 4 and Sprockets 3 don't quite get along as per the thread here thus the versioning not working as intended: https://github.com/rails/sprockets-rails/issues/240
Rails 4 selective asset digest
All files get digested. In Rails 3 all files also had a copy without digest but this was removed in Rails 4. Now you're supposed to have non digested assets in /public
. A workaround is to create a rake task which copies the assets. More details can be found in https://github.com/rails/sprockets-rails/issues/49 in there is also a monkey patch to restore the old behavior.
Referencing rails assets without the digest?
You can try asset_path('app.js', :digest => false)
or disable digest in the prodution env:
# config/environments/prodution.rb
config.assets.digest = false
Rails pipeline
Rails 4 asset pipeline doesn't overwrite assets with asset_path references to other assets
A solution was suggested here which involves using the depend_on
or depend_on_asset
directive. In my case adding this to the .js.erb
file works:
//= depend_on_asset views/template.html
url = '<%= asset_path('views/template.html') %>'
This will recompile this file any time there is a change to views/template.html
as desired. Rails Asset Pipeline: Return digest version when non-digest requested
I think the must elegant way is doing some Controller to do some redirect 302 to you assets.
You can paste to your client a code link /public-assets/my_assets
In your route create the route :
match '/public-assets/:asset_name' => 'PublicAsset#index'
And create your controller PublicAssetControllerclass PublicAssetContoller < ApplicationController::Base
def index
redirect_to asset_path(params[:asset_name])
end
end
Rails not using digested assets in production
You may need to run the precompile task on production after deployment.
I am under assumption that Heroku does this by default.
There are a few examples found here:
https://gist.github.com/fancyremarker/9652688
Related Topics
Ruby: Class C Includes Module M; Including Module N in M Does Not Affect C. What Gives
Parsing a CSV File Using Different Encodings and Libraries
Rails3 Scope for Count of Children in Has_Many Relationship
How to Get Nokogiri to Parse and Return an Xml Document
Pod Install in Xcode Bots Trigger
Ruby Gem Development - How to Use Activerecord
Securely Display an Image Uploaded with Paperclip Gem
How to Directly Install a Gem from a Git Repository
Rails Redirecting Invalid Route to Root
Require Tree in Asset Pipeline
Should I Move My Custom Methods to Model from Controller
Reading Files in a Zip Archive, Without Unzipping The Archive
Filtering Sensitive Data with Vcr