Force reload of static assets with embedded ruby in Rails - ruby-on-rails

I have a js.erb file that uses an environment variable to set a string that will occasionally change. I would like to be able to change the environment variable and immediately be able to load an updated javascript file, but since the source erb file doesn't change, Rails doesn't know it needs to be compiled again. Is there any way I can force it to recompile?
Note: this is in a dev/test environment, not a production environment with precompiled assets.
Note #2: this feature has actually been addressed by sprockets, however the most recent release is older than the PR that adds the feature. I'm looking for a temporary solution that accomplishes the same thing (see https://github.com/rails/sprockets/pull/365)

I was able to accomplish my goal with the answer from this question How to add a rails asset dependency to an environment variable with sprockets?
However, first I had to upgrade sprockets to >= 3.0.0.

Related

Sprockets cache not invalidated by file change

I'm running a test Ruby-on-Rails app using Webrick in a test environment. The automated end-to-end test accesses an admin page which causes a JavaScript file to be updated which is used by another admin page. The problem is that the second admin page does not see the update, but instead gets the old copy of the JavaScript file. I can see the changed file on the file system, but even if use curl from the command line, I still get the old version of the file. The test used to work (at least with Rails 4.0, if not 4.1). It is just now that I am trying to update to Rails 4.2 that this problem has arisen.
Is there something I can do to to tell Rails/Sprockets to forget its old cached copy of the JavaScript that was updated? I know when I am updating it, and wouldn't mind even resetting Sprocket's entire cache if I couldn't do it selectively. What I can't do is restart the server each time a JavaScript file gets updated.
I tried many approaches to making Sprockets "forget" its cached copy, but it seemed very determined to remember, and I began to have the sense that I was fighting against a firmly entrenched design decision. In the end I decided that, just for my generated-on-the-fly JavaScript files, I would avoid sprockets altogether, which meant handling the compiling and fingerprinting of the files myself, and writing my own version of javascript_include_tag just for those generated files.
For reference, the compiling and fingerprinting is actually fairly easy:
require "uglifier"
require "digest"
minified_content = Uglifier.compile(File.read(my_generated_js_file))
fingerprint = Digest::MD5.hexdigest(minified_content)
fingerprinted_file = File.basename(basename, '.js') + '-' + fingerprint + '.js'
(and then just write out the fingerprinted file to public/assets).

Force recompilation of certain files in rails assets pipeline

I'm using ruby on rails 4.1.9.
Is there a way to define a whitelist of files that should be recompiled anytime, even if they don't change?
For example: I have a few .js.erb files injected with some Rails variables. So, even if the original file is not changing, they need recompilation.

Has asset fingerprinting changed in Rails 4.2?

I recently upgraded a Rails 4.1 app to 4.2. When I look at the page source in development mode, all of the assets now have a fingerprint associated with them:
/assets/application-7d90cdd9d3a3cc2a3445c0e8b748db14.js?body=1
Pre 4.2 I think it used to be
/assets/application.js?body=1
Has something changed or did I miss a config setting?
Yes, Rails 4.2 now enables asset digests ("fingerprints") in development by default.
Here is the commit:
https://github.com/rails/rails/commit/f369bcf9a0dba0a945ca6fe53343c042f54c1fcf
Why the change? It is a long story, but my understanding is that the Rails team wants development and production behavior to be more similar in order to prevent unexpected errors when deploying.
Another related change in Rails 4 is that it no longer generates assets without digests in production. In order to catch mistakes earlier (i.e. before you deploy to production), the development settings have been changed to match the production digest behavior.
To see why this helps, here is an example:
Suppose your code (or a jQuery plugin you're using, let's say) references an asset directly by its path, like this: /assets/logo.png. Before Rails 4.2, this would work perfectly fine in development. But when you deploy, surprise! /assets/logo.png doesn't exist. In order for it to work in production, you would need to use the asset_path helper to generate the correct path with the fingerprint.
By forcing you to use digests/fingerprints in development, Rails 4.2 helps surface this mistake while you are still in development. No more unpleasant surprises at deploy time.
That said, these changes are... controversial, to say the least.
I've discovered this gem: https://github.com/alexspeller/non-stupid-digest-assets
it disables the digests.
From the readme:
Just put it in your Gemfile
gem "non-stupid-digest-assets"
If you want to whitelist non-digest assets for only certain files, you can configure a whitelist like this:
# config/initializers/non_digest_assets.rb
NonStupidDigestAssets.whitelist += [/tinymce\/.*/, "image.png"]
Be sure to give either a regex that will match the right assets or the logical path of the asset in question.
Note that the logical path is what you would provide to asset_url, so for an image at RAILS_ROOT/assets/images/foo.png the logical path is foo.png

When are compiled assets being cached in rails

When I precompile my assets for a rails 3.1 app with rake assets:precompile it spits out an old cached version if nothing changes in the asset files. I can tell because my erb is making use of a constant that I was trying to change elsewhere in my app. One work around is to alter one of the css files (eg by adding a space etc) before re-precompiling but this is a pain and I would like to try and disable this caching if it is possible. Any ideas???
This is the expected behavior of the pipeline - the ERB is evaluated only once when you precompile. The value at compile time is the value you get in the file.
The caching is based on the checking the timestamp of the files. You could run Sprockets in production without precompiling (this is called live compiling), but you cannot turn off the caching because the performance would be dreadful - every single request would require Sprockets to recompile all the files.
Sorry :-(

Rails 3.1 asset pipeline: Ignore backup files from Emacs and other editors

In a Rails 3.1 project, if I edit app/assets/javascripts/users.js.coffee using Emacs, then Emacs creates a backup file named app/assets/javascripts/users.js.coffee~ (note the trailing "~").
Unfortunately, the new Rails 3.1 asset pipeline sees this .coffee~ file, and injects it directly into the generated application.js, which in turn causes JavaScript errors in the browser.
I could turn off backups in Emacs by writing:
(setq backup-directory-alist nil)
...or I could use:
(setq backup-directory-alist `(("." . "~/.emacs-backups")))
...to move them into another directory.
But this would require every Emacs user on the project to reconfigure their Emacs, which is undesirable. I would prefer to configure Rails 3.1 to ignore files ending in .coffee~. Is there an easy way to do this?
I thought this was a defect in the require_tree method; and it sort of is,
seems to be a few issues filed on this:
https://github.com/rails/rails/issues/1863#issuecomment-1543809 (Rails)
https://github.com/sstephenson/sprockets/pull/119 (Sprockets)
https://github.com/sstephenson/hike/issues/9 (Hike, fix was made here)
looks like it was fixed recently, after Rails rc4 (hike-1.1.0), looks like hike-1.2.0 has been released with the fix, you could try updating your Gemfile to use the newer version

Resources