Hashed assets on multi-site Rails site - ruby-on-rails

Rails: 4.2.7.1, Ruby: 2.3.1
We used to use non-hashed assets for serving our assets on our multi-site application by hardcoding the path to the asset in the individual site's headers. We are now pre-compiling hashed assets with Sprockets on each deploy in production with these settings:
production.rb
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.serve_static_files = true
config.assets.prefix = "/assets"
config.assets.digest = true
config.assets.initialize_on_precompile = true
We end up with hashed assets, for example, in /public/assets/skins/site1/skin-70ee38249235f8521a243a8f955ed08c.css.
We have a skin file for each path that we use to load our styles per site. We do generate a site application.css that remains unused. Each skin file contains variables for each site and then imports the site's manifest file containing the sass stylesheets.
What we tried to do was create a way for our CMS to look for the hashed asset:
stylesheet_link_tag("/assets/skins/site1/skin.css", media: "all")
The issue is that the site is still looking for the non-hashed skin file. If we have the plain skin.css, it will work.
Same goes for Javascript:
javascript_include_tag "/assets/admin.js"
It will look for the non-hashed asset, even though the hashed asset is present. I tried to remove the "/assets" part from the link tags and it will fail.
Is there a setting that we are missing to have Rails look for the proper hashed asset? Any advice is appreciated.

Related

Referencing rails assets without the digest?

I am referencing assets in my rails app directly, for ex. background-image: url('/assets/bg.png').
But I just realized this wouldn't work in production since digested assets are served (/assets/bg-dddasd434r4tfdfs...sada.png) in production.
Is my only choice to use helper methods (for ex, image-url) throughout the application or is there a more simpler solution to this?
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
In config/application.rb change the value of
config.assets.digest to false
This is an ancient question, but since I happened upon it with Google...
In Rails 5 there is the asset_path helper which even in the .scss files can return the proper path to a file.

duplicate Rails 4 asset fingerprint file on Heroku

I'm getting duplicate asset fingerprint javascript file on Heroku production.
This initially creates around 3-4 files then after a while (a day), it creates another set of those files again. Also every time I refresh those files get rotated in the source.
On production.rb:
config.assets.enabled = true
config.assets.digest = true
config.action_controller.asset_host = "//#{ENV['FOG_DIRECTORY']}.s3.amazonaws.com"
config.assets.initialize_on_precompile = true
config.assets.precompile += %w( '.woff', '.eot', '.svg', '.ttf', '*.css.scss', application_user.js, popcorn.js )
On application.rb:
config.assets.enabled = true
config.assets.digest = true
Surely this doesn't matter?
Structure
The Rails structure is such that it should allow you to use whatever fingerprinted file you need, and it will show (using the dynamic javascript include helpers)
If you're unable to read a particular file because it's not exactly the same as it was before is, in my opinion, a highlight of a poor system design
Files
I think I remember your issue from another day -- you can just use the helper method to call the files you need. It shouldn't cause any issues with the different names. It's all part of the asset pipeline
I'd recommend looking into how you're calling the files - if you're trying to call the hashed filename directly, you're going to have an issue

Disable Sprockets asset caching in development

I'm using Rails 3.2.13 and the Rails Asset Pipeline. I want to use the Asset Pipeline so I can use SASS and CoffeeScript and ERB for my assets and have the Pipeline automatically compile them, so I cannot turn off the pipeline in development. I am not precompiling assets in development ever and there is not even a public/assets/ directory.
However, when I make changes to an included file, such as to a _partial.html.erb file that is included (rendered) in a layout.html.erb file, without changing the file doing the including itself (in this example layout.html.erb), Sprockets doesn't detect the change and invalidate the cache, so I keep getting the same stale file. When I'm doing this in active development, I want to disable any caching of assets so I can get the changes on every request but I cannot figure out how to do this. I have set all of the following in my development.rb:
config.action_controller.perform_caching = false
config.action_dispatch.rack_cache = nil
config.middleware.delete Rack::Cache
config.assets.debug = true
config.assets.compress = false
config.cache_classes = false
Still, even with this, files show up under tmp/cache/assets/ and tmp/cache/sass/ and changes are not available on future requests. Right now I have to manually delete those directories every time I want to see a change.
Unfortunately, the entire contents of the How Caching Works section of the RoR Guide for the Asset Pipeline is:
Sprockets uses the default Rails cache store to cache assets in
development and production.
TODO: Add more about changing the default store.
So, how can I get Sprockets to compile assets on demand but not cache the results?
Here's the magic incantation:
config.assets.cache_store = :null_store # Disables the Asset cache
config.sass.cache = false # Disable the SASS compiler cache
The asset pipeline has it's own instance of a cache and setting config.assets.cache = false does nothing, so you have to set its cache to be the null_store to disable it.
Even then, the SASS compiler has it's own cache, and if you need to disable it, you have to disable it separately.
I created the following gist (https://gist.github.com/metaskills/9028312) that does just this and found it is the only way that works for me.
# In config/initializers/sprockets.rb
require 'sprockets'
require 'sprockets/server'
Sprockets::Server.class_eval do
private
def headers_with_rails_env_check(*args)
headers_without_rails_env_check(*args).tap do |headers|
if Rails.env.development?
headers["Cache-Control"] = "no-cache"
headers.delete "Last-Modified"
headers.delete "ETag"
end
end
end
alias_method_chain :headers, :rails_env_check
end
The accepted answer is not doing it correctly and it degrades the performance in development by disabling cache totally.
Answering your original question, you want changes to referenced files to invalidate the asset cache even if not included directly.
The solution is by simply declaring such dependency such that sprockets knows that the cache should be invalidated:
# layout.html.erb
<% depend_on Rails.root.join('app').join('views').join('_partial.html.erb') %>
# replace the above with the correct path, could also be relative but didn't try

Select rails 3 assets based on environment

In a Rails 3 application, I would like to be able to use unminified javascript and css files in my development environment for debugging and such, and minified versions in production.
I can think of a few hacky solutions, but ideally I'd like javascript_include_tag and friends to automatically select the right asset file.
Ideas?
Add your js normally using
javascript_include_tag
In your development.rb set:
config.assets.compress = false
and in production.rb use:
config.assets.compress = true

asset compression causing javascripts not to work

All my javascripts stopped working in production when I compiled them into application.js. I fixed this issue by turning asset debug on in production like so:
config.serve_static_assets = false
# Compress JavaScripts and CSS
config.assets.compress = false
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
# Generate digests for assets URLs
config.assets.digest = true
config.assets.debug = true
my question is if there are any problems with leaving asset debug on in production mode besides people being able to see my js files. Is there a setting I'm missing that would allow me to compress the JS and it still would work? I'd like to be able to compress them but the javascript just isn't loading when I try it.
Sometimes compressed js just doesn't work, could be because of the order it was done, or something else.

Resources