Upgrading Rails 4

Upgrading Rails 3.2 to Rails 4

You’ll need to be running Ruby 1.9.3 or later

Create New branch

$ git checkout -b rails4

Gemfile Changes:

Replace: gem 'rails', '3.2.x'

with: gem 'rails', '4.0.0.rc1'

Rails 4 removes 'assets' group, so remove assets group and change the gem version included in assets compatible to rails 4 like:

gem 'coffee-rails', '~> 3.2.1' => gem 'coffee-rails', '~> 4.0.0.rc1'

gem 'less-rails'

gem 'sass-rails', '~> 3.2.3' => gem 'sass-rails', '~> 4.0.0.rc1'

gem 'uglifier', '>= 1.0.3'


Now run "$ bundle update" to install new version of gems and "$ bundle outdated" to finding out of date gems. So update all the oudated gems to the version supported by Rails 4.

Ex: Let's say result of "$ bundle outdated" command is like,

Outdated gems included in the bundle:
* paper_trail (2.7.1 > 1.6.4)
.
.
.

Because it couldn’t find a newer version compatible with Rails 4 so just replace this gem like

gem 'paper_trail', github: 'airblade/paper_trail', branch: 'rails4'

and now run bundle update so it will fetch newer version of Papertrail from the Github project and completes successfully.

So just like that you have to update all outdated gems in your application with appropriate version.

Also page caching, observers, protected model attributes and ActiveResource have been removed in Rails 4. So if any of these features used in your application, then it's easy to add back through gems.

gem 'rails-observers'
gem 'actionpack-page_caching'
gem 'actionpack-action_caching'
gem 'activerecord-deprecated_finders'

Production environment in Rails 4 uses static precompiled assets and will not generate dynamically. So execute this command to precompile assets for production environment
$ RAILS_ENV=production bundle exec rake assets:precompile

Routes.rb File changes

'match' is not accepted in Rails 4.
There are two options for update match,

  1. Replace 'match' with appropriate request(get, post etc).

match 'new', to: 'inventories#new' => get 'new', to: 'inventories#new'

  1. 'via: [:get, :post]'

match 'new', to: 'inventories#new', via: :get

Replace 'put' => 'patch'

Configuration Changes

/config/application.rb

Replace

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

with: Bundler.require(:default, Rails.env)

Remove 'config.active_record.whitelist_attributes = false'

The asset pipeline is enabled by default in Rails 4, so need to set 'config.assets.enabled = false', if you are not using asset pipeline for your application, otherwise you can remove this option.

/config/development.rb

Set 'config.eager_load = false'

Remove 'config.whiny_nils = true'

Remove 'config.active_record.mass_assignment_sanitizer = :strict'

You can also remove the other options (like 'best_standards_support', 'auto_explain_threshold_in_seconds', 'assets.compress' etc..) which are no longer required.

/config/production.rb

Add 'config.eager_load = true'

Replace: 'config.assets.compress = true'

with: 'config.assets.js_compressor = :uglifier'

/config/test.rb

Add 'config.eager_load = false'

Remove 'config.whiny_nils = true'

Remove 'config.active_record.mass_assignment_sanitizer = :strict'

/config/initializers/secret_token.rb

Screencaster::Application.config.secret_token = '762a2f23950e306....'

Screencaster::Application.config.secret_key_base = 'xx762a2f23950e3..'

Once you’ve successfully migrated your application you can remove the secret_token option.

Models and controller level changes

In Rails 4, all scopes must use lambda:

Ex:

Replace: scope :active, where(status: 'active')

with: scope :active, -> { where(status: 'active') }

Clean up the deprecations

  1. find_all_by_

    User.find_all_by_name('abc') => User.where(name: 'abc')
  2. find_last_by_

    User.find_last_by_name('abc') => User.where(name: 'abc').last
  3. find_or_create_by_

    User.find_or_create_by_name('abc') => User.where(name: 'abc').first_or_create
  4. find_or_create_by_...!

    User.find_or_create_by_name!('abc') => User.where(name: 'abc').first_or_create!
  5. find_or_initialize_by_

    User.find_or_initialize_by_name('abc') => User.where(name: 'abc').first_or_initialize
  6. scoped_by_

    User.scoped_by_name('abc') => User.where(name: 'abc')

Rails 4 use Strong parameter(strong parameter) So remove attributes from models and put the restrictions in the controller

Ex: Let's i have a product module

class Product < ActiveRecord::Base
attr_accessible :description, :image_url, :price, :title
has_many :product_events,:dependent => :destroy
end
and Product_controller
def create
@product = Product.new(params[:product])
respond_to do |format|
.
.
end

Remove first line from product model and create a private method in product controller

def product_params
params.require(:episode).permit(:description, :image_url, :price, :title)
end

and Replace: Product.new(params[:product])

with: Product.new(product_params)

Replace: before_filter' with 'before_action'

Also the /vendor/plugins is no longer used so you can move the plugins out into a gem or into '/lib'.

There are many more Rails 4 features but i am exploring now so i will post in future.

Thanks

You can check the following link for more details: http://railscasts.com/episodes/400-what-s-new-in-rails-4(Rails 4 Feature)

Strong Parameter(Strong Parameter)

Sunil Sharma

I am a Ruby on Rails developer, passionate about building interesting and innovative web and mobile apps. | Ruby on Rails | Ember.js | Cordova | Travelling | Party | Trekking ...

Read More