13 Mar 2015
A Guide for Upgrading to Ruby on Rails 4.2.0

A Guide for Upgrading to Ruby on Rails 4.2.0

As you might have already heard, the latest stuff for upgrading rails was finally released at the end of the last year, viz. 4.2.0 was released on Dec 19, 2014. Well, here is the quick overview of its major tools:

Active Job 

It is a common interface on top of queuing systems like Resque, Delayed Job, Sidekiq, etc.

Active Job is a framework for declaring jobs and making them run on a variety of queueing backends. These jobs can be everything from regularly scheduled clean-ups, to billing charges, to mailings; anything that can be separated into small units of work and run in parallel.

Also there could be other framework features and other gems built on top of that, without having to worry about API differences between Delayed Job and Resque.

Usage

Set the queue adapter for Active Job:

ActiveJob::Base.queue_adapter = :inline # default queue adapter

Declare a job like so:

classMyJob< ActiveJob::Base
  queue_as :my_jobs
  defperform(record)
    record.do_work
  end
end

Enqueue a job like so:

MyJob.perform_later record  # Enqueue a job to be performed as soon the queueing system is free.
MyJob.set(wait_until: Date.tomorrow.noon).perform_later(record)  # Enqueue a job to be performed tomorrow at noon.
MyJob.set(wait: 1.week).perform_later(record) # Enqueue a job to be performed 1 week from now.

That's all.

GlobalID support

Active Job supports GlobalID serialization for parameters.

Tip:

A Global ID is a URI that uniquely identifies a model instance:

gid://YourApp/Some::Model/id

This is helpful when you need a single identifier to reference different classes of objects.

One example is job scheduling:

we need to reference a model object rather than serialize the object itself. We can pass a Global ID that can be used to locate the model when it's time to perform the job. The job scheduler doesn't need to know the details of model naming and IDs, just that it has a global identifier that references a model.

Another example:

a drop-down list of options, consisting of both Users and Groups. Normally we'd need to come up with our own ad hoc scheme to reference them. With Global IDs, we have a universal identifier that works for objects of both classes.

This makes it possible to pass live Active Record objects to your job instead of class / id pairs, which you then have to manually deserialize. Before, jobs would look like this:

classTrashableCleanupJob
  defperform(trashable_class, trashable_id, depth)
    trashable = trashable_class.constantize.find(trashable_id)
    trashable.cleanup(depth)
  end
end

 Now you can simply do:

classTrashableCleanupJob
  defperform(trashable, depth)
    trashable.cleanup(depth)
  end
end

Asynchronous Mails

Active Jobs also serves as the backend for Action Mailer's #deliver_later functionality that makes it easy to turn any mailing into a job for running later. That's one of the most common jobs in a modern web application: sending emails outside of the request-response cycle, so the user doesn't have to wait for it.

Sending emails right away is still possible with deliver_now.

Adequate Record

Adequate Record is a set of performance improvements in Active Record that makes find_by calls and some association queries up to 2x faster.

It works by caching common SQL queries as prepared statements and reusing them on similar calls, skipping most of the query-generation work on subsequent calls.

Active Record will automatically take advantage of this feature on supported operations without any user involvement or code changes. Here are some examples of supported operations:

Post.find(1)  # First call generates and cache the prepared statement
Post.find(2)  # Subsequent calls reuse the cached prepared statement
Post.find_by_title('first post')
Post.find_by_title('second post') 
Post.find_by(title: 'first post')
Post.find_by(title: 'second post')
post.comments
post.comments(true)

 

It's important to highlight that, as the examples above suggest, the prepared statements do not cache the values passed in the method calls; rather, they have placeholders for them.

Web Console

New applications generated with Rails 4.2 now come with the Web Console gem by default.

Web Console is a set of debugging tools for your Rails application.

A debugging tool in the default error page.

An interactive console is launched automatically in the default Rails error page. It makes it easy to inspect the stack trace and execute Ruby code in the stack trace's bindings.

A debugging tool in your controllers and views.

Drop <%= console %> anywhere in a view to launch an interactive console session and execute code in it. Drop console anywhere in a controller and do the same in the context of the controller action.

Installation:

To install it in your current application, add the following to your Gemfile.

group :development do
  gem 'web-console', '~> 2.0'
end

After you save the Gemfile changes, make sure to run bundle install and restart your server. 

Configuration

It allows you to execute arbitrary code on the server, so you should be very careful; who you give access to it. 

config.web_console.whitelisted_ips

By default, only requests coming from 127.0.0.1 are allowed.

config.web_console.whitelisted_ips lets you control which IP's have access to the console.

Let's say you want to share your console with 192.168.0.100. You can do this so: 

classApplication< Rails::Application
  config.web_console.whitelisted_ips = %w( 127.0.0.1 192.168.0.100 )
end

From the example, you can guess that config.web_console.whitelisted_ips accepts an array of ip addresses, provided as strings.

If you want to whitelist a whole network, you can do it like this: 

classApplication< Rails::Application
  config.web_console.whitelisted_ips = '192.168.0.0/16'
end

Again, note that this network doesn't allow 127.0.0.1. If you want to access the console, you have to do so from it's external IP or add 127.0.0.1 to the mix.

Foreign Key Support

The migration DSL now supports adding and removing foreign keys. At this time, only the mysql, mysql2 and postgresql adapters support foreign keys.

# add a foreign key to `articles.author_id` referencing `authors.id`
add_foreign_key :articles, :authors
# add a foreign key to `articles.author_id` referencing `users.lng_id`
add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"
# remove the foreign key on `accounts.branch_id`
remove_foreign_key :accounts, :branches
# remove the foreign key on `accounts.owner_id`
remove_foreign_key :accounts, column: :owner_id

Incompatibilities

1. Render with a String Argument

Previously, calling render "foo/bar" in a controller action was equivalent to render file: "foo/bar". In Rails 4.2, this has been changed to mean render template: "foo/bar" instead. If you need to render a file, please change your code to use the explicit form (render file: "foo/bar") instead.

2. respond_with / Class-Level respond_to

respond_with and the corresponding class-level respond_to have been moved to the responders gem. Add gem 'responders', '~> 2.0' to your Gemfile to use it:

# app/controllers/users_controller.rb
classUsersController< ApplicationController
  respond_to :html, :json
 
  defshow
    @user = User.find(params[:id])
    respond_with @user
  end
end

Instance-level respond_to is unaffected:

# app/controllers/users_controller.rb
classUsersController< ApplicationController
  defshow
    @user = User.find(params[:id])
    respond_to do |format|
      format.html
      format.json { render json: @user }
    end
  end
end

 

3. Default Host for rails server

Due to a change in Rack, rails server now listens on localhost instead of 0.0.0.0 by default. This should have minimal impact on the standard development workflow as both http://127.0.0.1:3000 and http://localhost:3000 will continue to work as before on your own machine.

4. HTML Sanitizer

The HTML sanitizer has been replaced with a new, more robust, implementation built upon Loofahand Nokogiri. The new sanitizer is more secure and its sanitization is more powerful and flexible.

Due to the new algorithm, the sanitized output may be different for certain pathological inputs.

If you have a particular need for the exact output of the old sanitizer, you can add the rails-deprecated_sanitizer gem to the Gemfile, to have the old behavior.

rails-deprecated_sanitizer will be supported for Rails 4.2 only; it will not be maintained for Rails 5.0.

5. assert_select

assert_select is now based on Nokogiri. As a result, some previously-valid selectors are now unsupported. If your application is using any of these spellings, you will need to update them:

Values in attribute selectors may need to be quoted if they contain non-alphanumeric characters.
# before
a[href=/]
a[href$=/]
 
# now
a[href="/"]
a[href$="/"]

DOMs built from HTML source containing invalid HTML with improperly nested elements may differ. For example:

# content: <div><i><p></i></div>
# before:
assert_select('div > i')  # => true
assert_select('div > p')  # => false
assert_select('i > p')    # => true
 
# now:
assert_select('div > i')  # => true
assert_select('div > p')  # => true
assert_select('i > p')    # => false

If the data selected contains entities, the value selected for comparison used to be raw (e.g. AT&amp;T), and now is evaluated (e.g. AT&T).

# content: <p>AT&amp;T</p>
# before:
assert_select('p', 'AT&T')  # => true
assert_select('p', 'AT&T')      # => false
 
# now:
assert_select('p', 'AT&T')      # => true
assert_select('p', 'AT&T')  # => false

There are hundreds of posts on this topic. So please feel free to share others in the comments, to make this resource list longer and better. 

Similar posts:


Favourite posts

What it Takes to Get an e-Commerce Site Online

Getting an e-Commerce website online might sound like a huge undertaking,...

WebView Interactions with JavaScript

WebView displays web pages. But we are interested not only in web-content...

Google Maps API for Android

Google Maps is a very famous and helpful service, which firmly entrenched...

Unit Testing with RSpec

RSpec is an integral part of Test Drive Development (TDD) and its main id...

Client side JavaScript: Knockout in practice

When developing a web application that extensively works with user input ...

Accessing Field Configurations in JIRA for changing field description

Field configuration defines behavior of all standart (system) fields and ...

A Guide for Upgrading to Ruby on Rails 4.2.0

As you might have already heard, the latest stuff for upgrading rails was...