Upgrading sprockets-rails gem breaks tests - ruby-on-rails

After upgrading to sprockets-rails version 3.0 from version 2.3.3, the integration test below fails. It used to pass but now gives the error: Expected exactly 2 elements matching "img[src*='profile.gif']", found 0...
The test:
get user_path(#user1)
puts #response.body
assert_select "img[src*='profile.gif']", count: 2
puts #response.body confirms that the image is there twice as the body includes two times:
src="/assets/account/profile-3454be0beae***256dab6d.gif". Nevertheless the test fails.
Does anyone understand this? And how should I solve it?

Change seems to be related with rails 4 as stated in the Asset Pipeline documentation:
Rails 4 no longer sets default config values for Sprockets in test.rb,
so test.rb now requires Sprockets configuration. The old defaults in
the test environment are: config.assets.compile = true,
config.assets.compress = false, config.assets.debug = false and
config.assets.digest = false.
So if digests are not expected in the test environment it should be explicitly configured in the config/environments/test.rb file:
config.assets.digest = false

Related

Why Rails6+ started adding activesupport requires in config/environments/* by default?

I'm a bit late with Rails version upgrade. What surprised me was a bunch of active_support requires in config/environment/* files generated by Rails.
What are they for? Does it have something to do with Zeitwerk that was introduced in Rails6?
I don't remember them being present in older versions of Rails.
ag ^require config/environments
config/environments/development.rb
1:require "active_support/core_ext/integer/time"
config/environments/test.rb
1:require "active_support/core_ext/integer/time"
config/environments/production.rb
1:require "active_support/core_ext/integer/time"
Steps to reproduce:
rails new myapp
cat Gemfile | grep "^gem 'rails'"
gem 'rails', '~> 6.1.3', '>= 6.1.3.2'
I tried to find this update in rails/rails CHANGELOG and some git blaiming but that didn't help.
A little bit further down each environment file, the code that the require statement loads is used (or is referenced in comments, in the case of the production file). From the default development.rb:
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
if Rails.root.join('tmp/caching-dev.txt').exist?
config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}" # <- NOTE THIS LINE
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
That require statement adds support for expressions like 2.days.to_i - core_ext/integer/time loads some functions, but also requires core_ext/numeric/time.
So the require statement is being a good Ruby citizen, and making sure that the particular part of Rails that its code relies upon is guaranteed to be loaded in order to be able to parse that line correctly.
I don't know why it wasn't needed before (it could be a Zeitwerk-related issue, as you suggest, that's a part of Rails 6+ I'm not too familiar with yet).
But at the end of the day, if the whole Rails stack is loaded before this file is evaluated, the require won't have any additional effect – and if it's not, this file will load what it needs and then the rest of Rails will load as needed.

Disable Sprockets asset caching in development on Rails 4

Another question "Disable Sprockets asset caching in development" addresses how to disable Sprockets caching in Rails 3.2. How do you do the same thing on Rails 4? I am working on a gem that is deep in the asset pipeline and having to clear tmp/cache/* and restart Rails is getting tiring.
If you look at the Sprockets source, you can see that if cache_classes is true then app.assets gets set to app.assets.index, and the filesystem is no longer checked.
In order to get around this in development, you can add something similar to the following to your development.rb configuration:
# Sprockets configuration: prevent sprockets from caching assets in development
# when cache_classes is set to true
sprockets_env = nil
config.assets.configure do |env|
sprockets_env = env
# Sprockets environment configuration goes here
# env.js_compressor = :uglifier # or :closure, :yui
# env.css_compressor = :sass # or :yui
end
if config.cache_classes
config.after_initialize do
Rails.application.assets = sprockets_env
end
end
This essentially grabs a reverence to the Sprockets::Environment object before it is overwritten by the Sprockets::Index one, and allows the filesystem to be checked for new assets even when cache_classes is true. This seems to work for us in development, so hopefully it helps someone else out as well.

Rails 4 - javascript runtime required in production

I just updated a Rails 3.2.x app to 4.0.2.
When I deployed to production (ubuntu, MRI 2.0) I got the good old error about the lack of a javascript runtime.
I quickly fixed it by installing node, but it makes me wonder.
I prefer to precompile the assets locally, check them into git, and then push them to the production server along with the rest of the application.
With Rails 3.2 this system has always allowed me to not care about a js runtime in production, as the application doesn't need to compile coffeescript or run uglyfier.
So, the question is: what has changed with Rails 4? Is there a config option to control this behaviour?
I checked my (rails 4) config file, and I think that the production evironment is already configured to NOT fallback to live compilation.
assets-related config options:
config/application.rb
config.assets.precompile += ['html5shim.js']
config.assets.initialize_on_precompile = false
config/environments/production.rb
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Compress JavaScripts and CSS
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
In case someone hit this question as I did. I had the same problem and this link pointed me to the right direction: https://mattbrictson.com/upgrading-to-rails-4-with-capistrano. Specifically the following statement: In Rails 4, the standard Gemfile no longer has an :assets group, which means asset pipeline gems are always loaded in production, on all servers. I precompile my assets locally and upload them to production, so there is no reason to have JS runtime on production server.
In my case I added group :asset to my Gemfile putting there asset-related gems. In my case it was:
group :asset do
gem 'uglifier'
gem 'execjs'
end
My capistrano tasks on production install bundle without :asset group, so after this change JS runtime is no longer required on production.

Enable sprockets manifest asset paths in Rails 4 integration test

In tracking down some issues which only appear in precompiled assets, I would like to write some integration tests which reference the compiled assets. Try as I might, I have been unable to get integration tests responses which seem to reference assets that use digested paths.
I have tried adding the following to config/environments/test.rb
config.assets.compile = true
My layout has:
stylesheet_link_tag 'application'
Before running tests I run:
rake assets:precompile
Now when I run the integration tests I'm expecting the responses to include links in the form of assets/application-0f75109cfd6dc785c7bee4647913bc16.css, but it does it's simply `assets/application.css.
How could I enable such behavior?
I added the following to config/environments/test.rb:
config.assets.digest = true
According to the sprocket-rails README:
When enabled, fingerprints will be added to asset filenames.
This works in Rails 4.2.0.rc3

Can't run Rails app on Heroku: ActionView::Template::Error ("fontawesome.less" wasn't found

I'm using twitter-bootstrap-rails-2.2.7
Rails-3.2.11
sass-rails- 3.2.3
Running application returns back:
ActionView::Template::Error ("fontawesome.less" wasn't found....
Well, I downgraded twitter-bootstrap-rails to version 2.2.6 :)
You need to add it in config.assets.precompile (config/environments/production.rb)
from https://stackoverflow.com/a/7278355/600953
By default Rails assumes that you have your files precompiled in the production environment, if you want use live compiling (compile your assets during runtime) in production you must set the config.assets.compile to true.
# config/environments/production.rb
...
config.assets.compile = true
You can use this option to fallback to Sprockets when you are using precompiled assets but there are any missing precompiled files.
If config.assets.compile option is set to false and there are missing precompiled files you will get an "AssetNoPrecompiledError" indicating the name of the missing file.

Resources