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.
In production, Rails inserts an MD5 fingerprint into each filename so that the file is cached by the web browser
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.
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 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
Include rails precompiled asset pipeline .JS with md5 hash in filename in static page? or exclude it from getting a hash in the filename?
You'll find something like this in config/environments/production.rb
:
# Precompile additional assets (application.js, application.css, and all
# non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
You should add any assets you want to be able to link to individually, or additional manifest files, to the config.assets.precompile
array.
For example, you could make a maintenance.js
manifest file containing:
//= require foo
//= require bar
Add it to config.assets.precompile
:
config.assets.precompile += %w( maintenance.js )
And then on your maintenance page:
<%= javascript_link_tag 'maintenance' %>
See the precompiling assets section in the asset pipeline guide for more information.
Rails compiles assets both with and without md5 hash, why?
The reason it does it is so that you can access the files without knowing the MD5 fingerprint (for example in a non-rails application, or a file within the rails app which isn't compiled or run by the rails stack (e.g. a 500/502 status error page). In this case you would have to compile the assets then change the css/js links in the static HTML files each time you updated the code (thus causing a change in the MD5 hash).
So instead rails produces 2 copies of each asset file, one with the fingerprint in the filename, the other without (e.g. application-731bc240b0e8dbe7f2e6783811d2151a.css, and application.css). The fingerprinted version is obviously preferred (see 'what is fingerprinting and why should I care' in the rails asset pipeline guide). But the non-digested version is there as a fallback.
As a final thought on the matter I'd take a read of the following pull request to the rails git repo: https://github.com/rails/rails/pull/5379 where they are discussing the pros and cons of the non-digested filenames, and the possibility of being able to turn off compilation of them.
HTH
How does finger print digest gets calculated in Rails 4.2
This is true for Rails 4.2.x not sure about other versions
There are three parts (concatenated in the same order) involved in generating an md5 against a file.
- Sprockets::VERSION.
- Rails.application.assets.version that is generated here (https://github.com/rails/sprockets-rails/blob/2.x/lib/sprockets/railtie.rb#L91).
- Compiled file content.
The actual digest calculation in sprockets 2.x (for bundled assets) is being done here BundledAsset#L30
How to get asset version string from the asset pipeline
I would pass it in the json from the server.
To actually get the fingerprint, you can call digest_path on an asset to get it's MD5 sum appended value. See this SO answer, which the following snippet is taken from:
[1] pry(main)> Rails.application.assets.find_asset('application.js').digest_path
=> "application-ab07585c8c7b5329878b1c51ed68831e.js"
URI mismatch Rails generates MD5 digest in asset URL in production, but controller GET's a non-MD5 URL
Try to use plain html element declaration as follows:
<video width="640" height="500" control="controls">
<source src="../../../public/videos/car_circle.mp4" type="video/mp4">
</video>
Even .erb
file will still accept plain html declaration that should be free from any Rails' alteration.
Related Topics
Can't Get Rack-Cors Working in Rails Application
How to Run Rails Console in the Test Environment and Load Test_Helper.Rb
One Liner in Ruby for Displaying a Prompt, Getting Input, and Assigning to a Variable
Rails Search with Optional Parameters
How Does Defining [Square Bracket] Method in Ruby Work
Hashes of Hashes Idiom in Ruby
Ruby on Rails: Devise, Want to Add Invite Code
Rspec: How to Test If a Method Was Called
Cannot Execute "Rails Console" Due to an Error with Readline
How to Handle Errors with Httparty
Rails 4 + Devise: Invalid Route Name, Already in Use
Do Fixtures Trigger Model Callbacks
Why Doesn't Rails' "Errors.Full_Messages" Replace Attribute and Message Variables
How to Add a Primary Key to a Table in Rails