Note:This blog is brought to you by our good friends at The Hybrid Group. Be sure to check them out!
The transition from Ruby 1.9 to 2 doesn't bring as many changes as 1.8 to 1.9, but there's still a number of performance improvements, new features, and refinements added. Here's some of the cooler stuff:
Ruby 2 has a few patches that dramatically improve performance. The biggest of these is a substantial optimization to
Kernel#require, which speeds up Rails startup dramatically. Ruby 2 also has improved GC, VM optimizations, and improvements to floating point operations.
UTF-8 By Default
All Ruby scripts now default to UTF-8 encoding. This makes the
#encoding: utf-8 magic comment no longer necessary.
Previous versions of Ruby could approximate keyword arguments by using a hash as a method argument:
This works, but it's messier than it could be, it's hard to see with a glance at the method signature what arguments this method accepts, and it's difficult to set default values for arguments.
Ruby 2's new keyword arguments feature is still backed by a hash, but it's much easier to use now. Here's the same method rewritten to make use of it:
Note that though these act like keyword arguments, they're still just a hash underneath, so they're missing some functionality and flexibility that Python's keyword arguments have. For example:
Ruby 2 introduces the concept of a lazy Enumerable object. A lazy Enumerable will not consume excess memory, and will process individual elements as needed instead of the entire array/range passed to it.
As an example, this code in Ruby 1.9 would never complete:
While with Ruby 2's lazy evaluation:
Lazy enumeration has drawbacks, though. Ruby 2's lazy enumerators are much slower than normal ones, up to 4 times slower. This bug report goes into more detail about the issue.
Ruby 2 introduces the
__dir__ method. It returns the same result as
File.dirname(File.realpath(__FILE__)). It's useful when loading configuration files or modifying load paths.
Literal Symbol Array Syntax
You can now use
%I to make an array of symbols:
Ruby 2 brings support for DTrace probes, as well as a new Ruby class named
TracePoint that allows for inspecting an app's inner workings.
What's new and awesome in Rails 4?
Rails 4 isn't quite out yet, still at release candidate 1 as of this writing, but you can still preview the cool new features with
gem install rails --pre. Here's a sampling of some of the new stuff you'll find coming to Rails 4:
Mainly because of optimizations in Ruby 2, Rails 4 is much faster than Rails 3, particularly with startup time.
Rails 4 brings support for PostgreSQL's Hstore. Hstore is a schema-less key-value store inside of Postgres that allows for storing hash-like datasets directly inside of a column.
If you have a version of Postgres that supports Hstore, you can enable it by running this in a Postgres shell:
Alternatively, you can put this in a Rails migration:
Once Hstore is enabled, you'll have to create a column with a type of 'hstore'.
Now you can store any type of data you want in the
Rails 4 also includes the convenience method
store_accessor, which makes it even easier to access and update data inside the Hstore:
The main caveat to using Hstore is difficulty in migrating to a new database system in the future; but realistically, how often do you switch your backing database system?
PATCH is the new primary HTTP method for updating resources in Rails 4. This more correctly adheres to the principles of REST and Hypermedia APIs. For now, PUT requests still route to update actions, but this may change in a future release.
A new module introduced in Rails 4,
ActionController::Live allows for streaming data to clients. All you need to do is
include the module in a controller, and your app will now be enabled to stream arbitrary data.
You will, however, need to use a threaded webserver, like Puma or Rainbows!, in order to stream data. Actions from streaming controllers run in a seperate thread.
Here's an example streaming controller from the Rails 4 documentation:
This also allows for cool technologies like Server-sent events to be used.
Engine Yard doesn't currently support live streaming out of the box. The default server options on Engine Yard are Unicorn and Passenger, and neither of these support live streaming yet.
No More Dynamic Finders
Previous versions of Rails included dynamic finders for models, so we could use methods like
User.find_or_create_by_email_and_password. These relied on
method_missingand had messy implementations.
Rails 4 introduces new
find_or_initialize_by methods that all take hashes for arguments. For example:
These will be a big pain point while upgrading to Rails 4, but you can continue to use them with the
activerecord-deprecated_finders gem. This is a dependency of Rails 4 to ease the transition, but will be deprecated in Rails 4.1, and supported until Rails 5.
attr_accessible is the system for mass-assignment protection in Rails 3. It worked, but it's confusing and not very flexible. Some discussion happened around how to improve Rails' handling of mass assignment, and from this discussion the
strong_parameters gem was born.
As an example, let's take this controller example:
In Rails 3, you would protect against unexpected input with
attr_accessible declarations in the User model:
With Rails 4 and Strong Parameters, this validation moves from the model to the controller layer:
If you don't use the correct params, an
ActiveModel::ForbiddenAttributes exception is raised.
There's a few outstanding issues with strong parameters, notably with nested attributes. These will likely be resolved sometime soon, but you may want to watch for edge cases with complex models when updating.
Put Them Together
So what happens when you combine Ruby 2 and Rails 4?
Your app will be:
- More secure
- Easier to debug
Hopefully this article's gotten you excited about some of the awesome things you can expect with the new Ruby and Rails. The upgrade process is definitely not as punishing as going from Rails 2 to Rails 3. And as DHH says, the water's fine.
For more details on Rails 4, read our related posts: