What's new in Rails 5?
Rails 5.0 is almost here! The first beta version has been released already, and you can try out some of the shiny new features right away. So what are the new features? Let’s take a quick tour of the new features and major changes.
ActionCable
Websocket support in Rails is the most talked about feature in Rails 5. This will make it super easy to add realtime features to your app. If you’re planning to explore ActionCable, here’s a couple of getting started guides:
Attributes API
A new attributes API has been introduced that allows you to define
custom attributes on a model or override existing attributes.
For instance, you can create a MoneyType
attribute type,
and define how this gets stored as a price_in_cents
field in the database.
# app/models/product.rb
class Product < ApplicationRecord
attribute :price_in_cents, MoneyType.new
end
class MoneyType < ActiveRecord::Type::Integer
def type_cast(value)
# convert values like '$10.00' to 1000
end
end
product = Product.new(price_in_cents: '$10.00')
product.price_in_cents #=> 1000
It also allows you to override types of existing database attributes (eg. you were using a decimal field in the database, and now only need the values as integers), or even to define non-persisted attributes on a model. Read more about the attributes API here:
- Attributes API documentation
- Introduction to Rails 5 Attributes
- Using the Rails 5 Attributes API Today, in Rails 4.2
ApplicationRecord
And speaking of ActiveRecord, you might have noticed
that the Product
model above inherits from ApplicationRecord
,
not ActiveRecord::Base
.
This is because Rails now generates that class
so that we can add all our customizations there
instead of mokeypatching ActiveRecord::Base
.
Read more about it here:
ActiveRecord::Relation#or
After all this time, we finally have the #or
method in ActiveRecord.
We can call #or
on a relation and pass another relation as its argument
and it will generate an OR query.
We can use it like this:
class Issue < ApplicationRecord
scope :reported, -> { where(status: 'reported') }
scope :open, -> { where(status: 'open') }
end
active_issues = Issue.reported.or(Issue.open)
ActiveRecord::Relation#in_batches
The new #in_batches
method yields a relation,
unlike #find_in_batches
which yields an array.
We can use this method for things like this:
Person.where('age >= 18').in_batches(of: 1000) do |people|
people.update_all(can_vote: true)
end
ActiveRecord::Base#has_secure_token
If you need a random token in your models,
Rails 5 has introduced has_secure_token
.
Example usage:
class User < ApplicationRecord
has_secure_token :email_unsubscribe_token
end
user = User.create
user.email_unsubscribe_token #=> 'e2426a93718d1817a43abbaa'
user.regenerate_email_unsubscribe_token
Rails API
The rails-api gem has been merged into Rails.
It allows you to generate API-only Rails app
and strips out all the middleware that you don’t need
in an app that generates JSON responsed instead of HTML.
You can now generate an API-only app using the --api
option:
rails new my-app-api --api
ActionController::Renderer
View rendering has been moved out into ActionController::Renderer
and is available for use anywhere via ApplicationController.render
method.
This lets you render partials into strings and use them
in background jobs and other classes.
Here’s an example of how to render a partial using the render method:
MessagesController.render(partial: 'messages/message',
locals: { message: params[:message][:body] })
If you’re wondering why you would want to render views outside controllers you can see this in action in the code for the Getting Started with ActionCable guide, where it is used for rendering HTML into a string in background job which is then sent to the clients via websockets.
Turbolinks 3
The latest version of Turbolinks introduces partial replacement,
which allows you to replace only specific divs on a page.
Using data-turbolinks-permanent
, you can also transfer DOM elements
from page to page along with the states.
This is useful for sections like navbars that do not change across pages.
On the server side, you can trigger partial replacement
using additional options with redirect_to
or render
methods.
For example, take a look at the following code:
class CommentsController < ApplicationController
def create
@comment = Comment.new(comment_params)
if @comment.save
redirect_to comments_url, change: 'comments'
else
render :new, change: :new_comment
end
end
end
If the comment is saved successfully in the above case,
only the div with id “comments” is replaced
with the matching element from the rendered HTML at comments_url
.
In case of an error, only the ‘new_comment’ element, which is the comment form,
is replaced by the matching element from the response.
New command router
Ever accidentally typed rails db:migrate
or rake generate model
?
Figuring out which command to use is often confusing to beginners.
Now all such commands are routed through rails
,
so we will be able to use commands like rails db:migrate
.
The rake commands are still available if you want to use them.
Snappier development mode
In development mode, Rails reloads constants when it finds that the file has changed. Until now it was done by checking the mtimes for all the files on each request and reloading if something has changed. Rails 5 introduces an evented file system monitor which asynchronously calls Rails when something changes. As a result, it no longer needs to check all the files on each request, and this makes the development mode much faster. Read more about it here:
Test runner
The test runned for minitest has seen many improvements, including improved error messages, color output and the ability to run a single test by referring to the line. This has finally brought the minitest Read more about the improvements in the test runner here:
Supports only Ruby 2.2.2+
Rails has always pushed the community towards the latest Ruby versions, and 5.0 is no different. This version will only work on Ruby 2.2.2 and above. This lets Rails to improve performance by making use of the latest improvements in the Ruby garbage collector (like incremental GC and symbol GC).
If you’re upgrading Ruby anyway, you might want to look at Ruby 2.3 which was released recently with a bunch of new features.
Upgrading
With the release of Rails 5, all versions of Rails from 4.1.x and below will no longer be supported. Bug fixes will only be released for Rails 5.0.x and 4.2.x. Now would be a good time to upgrade, at least to 4.2.x if you haven’t already done so. If you’re planning to upgrade to Rails 5.0, these resources could be useful:
- Upgrading to Ruby on Rails 5.0 from Rails 4.2 – application use case
- A Guide for Upgrading Ruby on Rails
Links
The new features in Rails have been discussed in a few other places:
A lot of new features have been introduced in Rails 5, and I might have missed a few interesting ones. Please do leave a comment pointing out any interesting features I might have missed and I’ll add it to the list.