Why did Rails4 drop support for "assets" group in the Gemfile - asset-pipeline

In Rails 3, gems used exclusively to generate assets in the asset pipeline were properly placed in the assets group of the Gemfile:
...
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails'
gem 'coffee-rails'
gem 'uglifier'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
end
Now, according to the (still in progress) upgrade documentation:
Rails 4.0 removed the assets group from Gemfile. You'd need to remove that line from your Gemfile when upgrading.
Sure enough, making a new project with RC1 yields a Gemfile with asset-related gems included by default outside of any group:
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.0.0.rc1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0.rc1'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
...
Does this mean these gems will now be bundled in production builds by default? If so, why the change of heart? Is Rails 4 moving towards the dynamic generation of assets in production?

Previously the assets group existed to avoid unintended compilation-on-demand in production. As Rails 4 doesn't behave like that anymore, it made sense to remove the asset group.
This is explained in more detail in the commit that changed that. I extracted some quotes with the actual answer.
Some gems can be needed (in production) like coffee-rails if you are using coffee templates
and the fact that now assets are not precompiled on demand in production anymore.
(not precompiled on demand in production) Means that if you have that gems in production environment in 3.2.x and forget to precompile, Rails will do exactly what it does in development, precompile the assets that was requested. This is not true anymore in Rails 4, so if you don't precompile the assets using the tasks you will get a 404 when the assets are requests.

Rails 4 try to force you to precompile your assets before deployment. You have to precompile your assets with
$ RAILS_ENV=production bundle exec rake assets:precompile
And why?
I found this in Guide:
By default Rails assumes that assets have been precompiled and will be
served as static assets by your web server.
(Source: http://edgeguides.rubyonrails.org/asset_pipeline.html#in-production)
But many time you have to use these 'assets' gems in production... for example, if you use a js.coffee file in your views directory, then Rails needs coffee compiler in production mode as well.
So I guess, the reason of this change is performance improvement... and looks more simple as well. :)

We want coffeescript with AJAX (history), so coffee-rails moves out of the assets group.
sass-rails misbehaves (history), so it moves out of the assets group.
Axe the assets group.

Related

Heroku Production - ActionView::Template::Error (undefined method `directory' for #<Sprockets::Manifest:number>)

We have a react-rails app. Unfortunately, the app works on local development but not when deployed to heroku. When going to our default path on the app, we get the following error:
ActionView::Template::Error (undefined method 'directory' for #<Sprockets::Manifest:0x007fef13200aa8>)
We've figured out that it happens at this line in our view:
<%= react_component('NavBar', {}, {prerender: true}) %>
A few things about our app:
It uses browserify to compile our js.jsx.
We precompile using RAILS_ENV=production bundle exec rake assets:precompile after deleting the public/assets folder.
Works locally with both rails s and foreman start
We are using boostrap-sprockets. Even when removed, we still have this issue.
Here is our npm dependencies:
"dependencies": {
"browserify": "^10.2.4",
"browserify-incremental": "^1.5.0",
"classnames": "^2.2.3",
"reactify": "^1.1.0"
}
Here is our Gemfile
source 'https://rubygems.org'
gem 'rails', '4.2.3'
gem 'rails-api'
gem 'spring', :group => :development
gem 'active_model_serializers', '~> 0.10.0.rc1'
gem 'pg'
gem 'devise'
gem 'puma'
gem 'twitter'
gem 'react-rails', '~> 1.0'
gem 'browserify-rails', '~> 0.9.1'
gem 'bootstrap-sass', '~> 3.2.0'
gem 'sass-rails', '~> 5.0', '>= 5.0.4'
gem 'autoprefixer-rails'
group :test do
gem 'rspec-rails'
gem 'pry'
gem 'faker'
gem 'webmock'
end
group :development, :test do
gem 'factory_girl_rails'
end
group :production do
gem 'uglifier'
gem 'rails_12factor'
gem 'rspec'
end
ruby '2.2.4'
We would appreciate all help.
The solution from hours of searching on StackOverflow and github issues seems to be to remove
//= require react_ujs
from your application.js in your assets folder.
I ran into this same issue just today and followed the suggestions in: https://github.com/reactjs/react-rails/issues/443#issuecomment-180544359. I was still running into an error so for now I modified my heroku configurations (config/environments/staging.rb & config/environments/production.rb) to use
config.assets.compile = true
for now and server-side rendering worked fine. The react-rails folks said they have a pull request completed to fix this issue but I dont think it has been released yet.
Potentially relevant: rake assets:precompile undefined method directory? for nil:NilClass
This is an error that occurs when the Rails asset compiler (Sprockets) cannot find a directory that you've specified as the location of an asset for your project. My suggestion is to make sure that all your assets are being successfully deployed to heroku, and then check that your paths are set up correctly when you reference assets in your project for inclusion in a page.
Also see Eric C's answer pertaining to React-Rails specifically.
There was a bug in react-rails 1.6.0 which should be fixed in 1.6.1
Here's the patch:
https://github.com/reactjs/react-rails/pull/478
If the latest version doesn't work for you, please open an issue on the react-rails repo!

How to use gem from GitHub on Heroku?

I've forked the redis depository on github to https://github.com/lmirosevic/redis-rb
I added it to my Gemfile:
gem 'redis', :github => 'lmirosevic/redis-rb'
And I require the gem inside my Sinatra app:
require 'redis'
However it fails with the following error:
/app/vendor/ruby-2.0.0/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require': cannot load such file -- redis (LoadError)
Any suggestions on what could be wrong? It seems like it should work!
EDIT
I should note that the bundler phase is fine. The problem seems to be in the require step.
Bundler gives me this output:
Using redis (3.0.4) from git://github.com/lmirosevic/redis-rb (at master)
I should also say that my directory structure is something like this. Not sure if this makes a difference.
/
.env
Gemfile
Gemfile.lock
Procfile
/lib
my_sinatra_app.rb
/config
...
You must have
require 'bundler/setup'
in your app or else you're not really using bundler: this is what ensures that the gem versions loaded are the ones in your gemfile and sets up load paths for anything not installed globally.
Calling Bunder.setup allows you to control what groups are used, but if just using the default group is fine then you don't need to do this.
If you aren't setting up bundler then your gemfile is used to install the required versions of the gems but then bundler is no longer used - your app will used whatever gems are installed, whether the versions match or not and you won't be able to use gems that aren't installed in the default gem load paths.

Error syncing .less files when I push to Heroku app using asset_sync gem?

I have a Rails 3.2.12 app and I was trying to sync my assets using an Amazon S3 bucket and the asset_sync gem for my Heroku app.
I've looked on the whole github issues tracker and here on SO, but wasn't able to find an answer to this. So here's my question:
Is it possible to sync .less files using the asset_sync gem?
After I push to Heroku, I get in the logs this error:
Running: rake assets:precompile
rake aborted!
variable #inputHeight is undefined
(in /tmp/build_tejom7tf9zq9/app/assets/stylesheets/utils-and-mixins.less)
In order to config my app I followed the wiki from the asset_sync github page and to set my ENV variables I used the Built-in Initializer.
Here are the modifications in my production.rb file in order to fit the asset_sync requirements:
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
config.assets.precompile += [ '*.css' ]
# Serving Assets From S3 on Heroku
config.action_controller.asset_host = "//s3.amazonaws.com/test"
# store assets in a 'folder' instead of bucket root
config.assets.prefix = "/production/assets"
end
Any suggestion would be highly appreciated. Thank you
Edit 1:
I tried even running separately in my command line:
heroku run rake assets:precompile --app <yourapp>
but it didn't help, it threw the same error.
Edit 2:
I guess this is what you asked for:
....
gem 'less-rails', '~> 2.3.2'
gem 'twitter-bootstrap-rails', '2.2.6'
# Gems used only for assets and not required in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
gem 'therubyracer', '~> 0.11.4', platforms: :ruby
gem 'asset_sync'
end
Managed to make it work by writing in my production.rb the specific .css file names that I wanted to include to my S3 bucket:
# Enable serving of images, stylesheets, and JavaScripts from an asset server
config.action_controller.asset_host = "//s3.amazonaws.com/test"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
config.assets.precompile += %w( public.css users.css admin.css )

Heroku with ruby 1.9.3 causing many different crashes

I go to redeploy my heroku apps with a new gem in Gemfile and it crashes on startup
/app/vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:251:in `require': libruby.so.1.9: cannot open shared object file: No such file or directory - /app/vendor/bundle/ruby/1.9.1/gems/bcrypt-ruby-3.0.1/lib/bcrypt_ext.so (LoadError)
This is happening no matter what branch I deploy (old stable ones...) and only fixes by doing a heroku rollback.
I believe this is caused by heroku recently updating their ruby 1.9.3 because I was having this issue Heroku app crashes with 'libruby.so.1.9: cannot open shared object file' . Removing the nokogiri gem stopped the exception I was getting but then there's still this. More similar errors occur when I add new gems.
The whole problem was solved by deploying to a new heroku app but that's not something I can just do on my production server.
Any ideas on fixing the issue or somehow "refreshing" my app?
my gemfile:
source "https://rubygems.org"
ruby "1.9.3"
gem "rails", "3.2.3"
gem "thin"
# Bundle edge Rails instead:
# gem "rails", :git => "git://github.com/rails/rails.git"
gem "mongoid"
gem "devise"
gem "haml"
gem "sass"
gem "exceptional"
gem "kaminari"
gem "mongoid_search"
#gem "nokogiri"
gem "bson_ext"
gem "heroku-mongo-backup"
gem "aws-s3"
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem "haml-rails", "~> 0.3.4"
gem "sass-rails", "~> 3.2.3"
gem "coffee-rails", "~> 3.2.1"
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem "therubyracer", :platform => :ruby
gem "uglifier", ">= 1.0.3"
end
gem "jquery-rails"
group :test do
gem "mongoid-rspec"
end
# To use ActiveModel has_secure_password
# gem "bcrypt-ruby", "~> 3.0.0"
# To use Jbuilder templates for JSON
# gem "jbuilder"
# Use unicorn as the app server
# gem "unicorn"
# Deploy with Capistrano
# gem "capistrano"
# To use debugger
# gem "ruby-debug19", :require => "ruby-debug"
#
group :development do
gem "letter_opener"
end
Just FYI,
After contacting the Heroku support about this issue, you should follow these 3 simple steps:
Install this heroku-repo plugin: heroku plugins:install https://github.com/lstoll/heroku-repo.git
Run the following command: heroku repo:purge_cache
Deploy your app again.
Hope that helps!
This happened to me yesterday as well, was definitely something to do with Heroku.
I found fix and discussion on Twitter: https://twitter.com/bcardarella/status/256822171979100161
Just force-clear the gem file cache(clear gemfile, deploy, restore and deploy) and the app would start smoothly again.

rails 3.1, why my coffee scripts not working?

I am trying to test coffee script in my rails 3.1 project, but it doesn't get executed, or generated as javascript in the application.js
I have a controller Page, here is the pages.js.coffee:
test = (input) ->
alert input
test 'hello'
but that alert never get executed at http://127.0.0.1:3000/pages,
in fact, the application.js is just empty!
here is the GemFile in case it would help:
source 'http://rubygems.org'
gem 'rails', '3.1.0'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3'
gem 'devise', '1.4.8'
gem 'will_paginate', '~> 3.0.2'
#gem 'nested_form', :git => 'git://github.com/fxposter/nested_form.git'
gem "simple_form"
gem 'kaminari'
gem 'foreigner'
gem "cocoon"
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', " ~> 3.1.0"
gem 'coffee-rails', "~> 3.1.0"
gem 'uglifier'
end
gem "jquery-rails"
gem 'coffee-script'
gem 'haml'
# Use unicorn as the web server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
group :test do
# Pretty printed test output
gem 'turn', :require => false
end
EDIT
I have added those gems also and installed them, but, the coffee script is not executed
gem 'therubyracer'
gem 'coffee-script-source'
gem 'json'
gem 'execjs'
First: Having "coffee-rails" in your :assets group should be enough. Older versions had "coffee-script" in the :assets group.
Second: Where are you keeping your *.js.coffee files? You need to make sure they are in an "assets" folder some place. Start with app/assets/javascripts. If they aren't in your assets folder, they won't make it into the asset pipeline.
If you are doing that already, consider starting a new project and use the default configuration. It should work without any trouble. Compare the working project against the non-working project.
If all else fails, is it possible for you to share your project with us on GitHub?
Please check your config/application.rb, you should find a section like this:
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
#Bundler.require(:default, :assets, Rails.env)
end
I suspect you are not precompiling assets on deploy, even though you have it set to ignore the assets gems.

Resources