FB Web Tips

Digging Into Rails 4

By Arun Srinivasan

Rails 4 is rapidly approaching. In this article, let’s take a look at some of the new features that it offers, as well as the changes that may affect your current applications.

 


Some Bookkeeping

Cache digests are Rails 4′s solution for tracking the changes of aggressively cached templates.

There are several configuration and structural changes that comes with Rails 4.

Ruby >= 1.9.3

Rails 4 will only support Ruby 1.9.3+. Get ready for an upgrade if haven’t yet done so.

Threadsafe by Default

Rails 4 will be thread-safe by default, removing overhead and improving performance on threaded servers, like thin and puma. You need to ensure that your application (and its dependencies) are thread-safe, which typically means avoiding global state (e.g. class or global variables).


Aaron Patterson wrote and spoke about this subject. Definitely check those out!

No More vendor/plugins

Rails 3 embraced the idea of using gems to add custom functionality to Rails, and deprecated the use of plugins. Rails 4 completes this transition by removing the vendor/plugins directory altogether.

New Testing Directories

The default test directory naming scheme is more clear than in Rails 3.

The following directories will now be generated: test/models, test/helpers, test/controllers, test/mailers, and test/integration.

Executables

The script directory has been removed in favor of a new bin directory. This is where your app’s executables will live, and running rake rails:update:bin will put bundle, rake, and rails binstubs into your app’s bin directory.

This change can be useful in development, especially on a machine with multiple Ruby versions and gems. You can use bin/rails instead of bundle exec rails to ensure you run your executables in the correct environment.


Strong Parameters

Rails 4 tackles the mass assignment problem with the new Strong Parameters gem. A Rails 3 application might have a create action similar to the following example:

class UsersController < ApplicationController
  def create
    @user = User.create(params[:user])
    # ... check validity, redirect, etc.
  end
end

You can protect against unexpected input with declarations in the model:

class User < ActiveRecord::Base
  # Only allow the following attributes to be mass-assigned
  attr_accessible :name, :email
end

Using Rails 4′s Strong Parameters gem moves user input into the controller:

class UsersController < ApplicationController
  def create
    @user = User.create(user_params)
    # ... check validity, redirect, etc.
  end

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

As you can see, the params hash in your controller is not a normal hash. It’s actually an instance of ActionController::Parameters, which exposes the require and permit methods.

The require method ensures that the specified key is available in the params hash, and raises an ActionController::ParameterMissing exception if the key doesn’t exist.

The permit method protects you from unexpected mass assignment.

The call User.create(params[:user]) raises an ActiveModel::ForbiddenAttributesError exception, but using User.create(params.require(:user).permit(:name, :email)) makes it work without complaint.

The Rails 3 mass-assignment functionality is not only disabled in Rails 4, but has been extracted to a gem, in case you require that functionality.


Turbolinks

Rails 4 will be thread safe by default, removing overhead and improving performance.

A controversial new feature in Rails 4 is Turbolinks, a JavaScript plugin designed to make app navigation faster in the browser.

In browsers with pushState support, clicking a link causes the Turbolinks plugin to kick in. It makes an Ajax request, updates the URL with pushState (so your back button works) and uses JavaScript to update the and in the DOM. The speed gains come from not having to download and reparse JavaScript and CSS assets.

Turbolinks gracefully degrade for browsers which do not support pushState. In these situations, the page’s links behave as normal—causing a full page refresh.

Events and Cache

It’s common in applications to wait for a page to completely load before executing any JavaScript. For example:

$(document).ready(/* some function to run */) {
  // or event just $(/* some function to run */)
}

With Turbolinks, the page load events won’t fire when users navigate from “page” to “page” because the DOM never actually reloads. The library, therefore, adds new events that you can listen for, in order to perform any subsequent initializations that your app might need:

  • page:fetch – starting to fetch a page from the server
  • page:change – a page has been loaded
  • page:load – a page has been loaded from a server fetch
  • page:restore – a page has been loaded from a cache fetch

The page:change event always fires when Turbolinks loads a page, followed by page:load or page:restore, depending on whether the load came from the server or the cache.

Potential Issues

Rails 4 is coming, and it brings a slew of changes to the framework.

Turbolinks have a few issues that you might need to address:

  • Memory leaks: Turbolinks does not clear or reload your JavaScript when the page changes. You could potentially see the effects of memory leaks in your applications, especially if you use a lot of JavaScript.
  • Event Bindings: You have to take older browsers into consideration. Make sure you listen for page:* events, as well as DOMContentLoaded.
  • Client-side frameworks: Turbolinks may not play nicely with other client-side frameworks like Backbone, Angular, Knockout, Ember, etc.

Opting Out

You may opt out of Turbolinks by:

  1. removing turbolinks from your Gemfile, and
  2. removing the //= require turbolinks line from application.js

Caching

Rails 4 brings an overhauled caching strategy. First, action and page caching, as you may know it from previous versions of Rails, have been removed and extracted to gems: action and page, respectively.

Russian Dolls

The new kid on the block is Russian doll caching, or nested fragment caching. The easiest way to understand this system is to look at some code. Suppose that you have a project management application. You may have the following models:

class Milestone < ActiveRecord::Base
  has_many :todos
end

class Todo < ActiveRecord::Base
  belongs_to :milestone, :touch => true
end

The :touch option is required for this caching strategy to work properly. If a todo is added to a milestone, we need to break cache on the milestone to avoid serving stale views.

We now have finely-grained caches in our views. Consider this file as an example (app/views/milestones/show.html.erb):

<% cache @milestone do %>
  <h1><%= @milestone.name %></h1>
  <div class="description"><%= @milestone.description %></div>

  <ul class="todos">
    <%= render @milestone.todos %>
  </ul>
<% end %>

And in app/views/todos/_todo.html.erb:

<% cache todo do %>
  <li class="todo">
    <%= todo.description %>
    <span class="status"><%= todo.status %></span>
  </li>
<% end %>

Now, suppose that you have a milestone with ten todos. Editing only one todo causes the milestone’s cache to break, but when generating the HTML, all but one of the todo partials can be fetched from the cache, thus improving render times.

PATCH is now the new HTTP verb for updating resources.

You’re trading time for space, as this generates a lot of cruft in your cache. But, as DHH points out, cache stores like Memcached just chuck out old data to make space for new data. So this isn’t an issue in most cases.

Cache Digests

Cache digests are Rails 4′s solution for tracking the changes of aggressively cached templates. Rails 4 tracks templates and their dependencies, and it suffixes fragment cache keys with the MD5 digest of the template (and its dependencies). When you edit one of your templates, its cache key recieves the update, and you won’t have to manually version your templates.

For more information (and for use in Rails 3), check out the README for the cache digests gem.


Streaming, via ActionController::Live

The new ActionController::Live module provides the ability to stream data to clients. Simply include the module into a controller to enable your app to send arbitrary streamed data. You’ll have to use a threaded server, like thin and puma, in order to stream data; actions from streaming controllers run in a separate thread.

Here’s an example from the Rails 4 documentation:

class MyController < ActionController::Base
  include ActionController::Live

  def stream
    response.headers['Content-Type'] = 'text/event-stream'
    100.times {
      response.stream.write "hello worldn"
        sleep 1
    }
    response.stream.close
  end
end

As the docs note, there are three things to keep in mind:

  • You must write any headers before you call write or close on the response stream.
  • You have to call close on the response stream when you’re finished writing data.
  • Ensure that your actions are thread-safe, as they will run in a separate thread.

Niceties and Other Things

We’ve talked about the “headline” features in Rails 4. But this release is a big one, and includes a number of smaller changes to be aware of.

PATCH

As described in the Rails blog, PATCH is now the HTTP verb for updating resources.

This change will typically be transparent to developers, as PUT requests will still route to the update action for RESTful-style routes.

But it is a change that you should be aware of; PUT routing may change in the future.

Custom Flash Types

This small feature may help clean up some code. You can register your own flash types to use in redirect_to calls and in templates. For example:

# app/controllers/application_controller.rb
class ApplicationController
  add_flash_types :error, :catastrophe
end

# app/controllers/things_controller.rb
class ThingsController < ApplicationController
  def create
    # ... create a thing
  rescue Error => e
    redirect_to some_path, :error => e.message
  rescue Catastrophe => e
    redirect_to another_path, :catastrophe => e.message
  end
end

# app/views/layouts/application.html.erb
<div class="error"><%= error %></div>
<div class="catastrophe"><%= catastrophe %></div>

Deprecated Finders

Rails 4 deprecates the old-style finder option hashes, as well as all dynamic finder methods (with the exception of find_by_... and find_by_...). Instead, you’ll use where:

  • find_all_by_... can be rewritten using where(...).
  • find_last_by_... can be rewritten using where(...).last.
  • scoped_by_... can be rewritten using where(...).
  • find_or_initialize_by_... can be rewritten using where(...).first_or_initialize.
  • find_or_create_by_... can be rewritten using find_or_create_by(...) or where(...).first_or_create.
  • find_or_create_by_...! can be rewritten using find_or_create_by!(...) or where(...).first_or_create!.

The deprecated finders gem will be included as a dependency in 4.0. and removed in 4.1. The gem, however, will be around and maintained until 5.0.

Routing Concerns

Routing Concerns is an attempt to DRY up your config/routes.rb. The basic idea is to define common sub-resources (like comments) as concerns and include them in other resources/routes. Here’s the obvious example:

concern :commentable do
  resources :comments
end

concern :remarkable do
  resources :remarks
end

resources :posts, :concerns => :commentable  
resources :articles, :concerns => [:commentable, :remarkable] # can include several

The above is equivalent to the following Rails 3 code:

resources :posts do
  resources :comments
end

resources :articles do
  resources :comments
  resources :remarks
end

Personally, I’m not sure this adds much value; perhaps it makes sense for large applications with hundreds of routes.

Renamed Callbacks

Action callbacks in controllers have been renamed from *_filter to *_action. For example:

class UsersController < ApplicationController
  before_action :set_user, :except => [:index, :new, :create}
  before_action :require_the_president, :only => [:fire_the_missiles]

  private

  def set_user
    @user = somehow_find_and_set_the_user(params[:id])
  end

  def require_the_president
    @user.is_the_president?
  end
end

The old *_filter callbacks still work and are not deprecated; so, you can still use them if you wish. DHH’s reason for the change was:

“To avoid the misconception that these callbacks are only suited for transforming or halting the response. With the new style, it’s more inviting to use them as they were intended, such as setting shared ivars for views.”


Wrapping Up

Rails 4 is coming, bringing with it a slew of changes. I hope that this article has given you a sense of what to expect, and perhaps a launching point into investigating what this new version has to offer.

If you really want to wade into the deep end, check out our Tuts+ Premium course on Rails 4!

Source: Nettuts+


18 replies
  1. medical representative jobs
    medical representative jobs says:

    I used to be suggested this website by way of my cousin.
    I am no longer sure whether this submit is written by him as nobody
    else recognise such certain approximately my trouble.
    You are incredible! Thank you!

    Reply
  2. click through the up coming document
    click through the up coming document says:

    Hurrah, that’s what I was searching for, what a material! present here at this weblog, thanks admin of this website.

    Reply
  3. Nefful products negative ions clothing
    Nefful products negative ions clothing says:

    Hi there, You have performed a fantastic job. I will certainly digg it and for my part suggest to my friends. I’m confident they’ll be benefited from this site.

    Reply
  4. muscle enhancers
    muscle enhancers says:

    Magnificent goods from you, man. I’ve have in mind your stuff previous to and you’re simply
    too magnificent. I actually like what you have got here, certainly like
    what you’re stating and the best way by which you are saying it. You are making it enjoyable and you still care for to keep it sensible. I can’t wait to learn much more from you.
    That is really a tremendous site.

    Reply
  5. aloes forever
    aloes forever says:

    Ηellо i аm kаѵіn, іtѕ my first occаsіοn to commentіng
    anyρlace, when i гeaԁ this paгagгaph
    i thought i сοulԁ аlso crеаtе comment due to this goοd articlе.

    Reply
  6. check this out
    check this out says:

    I have learn some good stuff here. Definitely value bookmarking for revisiting.
    I wonder how so much attempt you put to create one of these magnificent informative website.

    Reply
  7. Mybloginfo.com
    Mybloginfo.com says:

    You truly constructed several great tips throughout your article, “Digging Into Rails 4 –
    Fire Bull Design Studio”. I may be heading back to your website
    soon enough. Thx ,Pansy

    Reply
  8. Rosita
    Rosita says:

    It’s really a cool and useful piece of info. I’m glad that you just
    shared this helpful information with us. Please stay us up to date
    like this. Thanks for sharing.

    Reply
  9. traffic exchanger
    traffic exchanger says:

    Its such as you read my mind! You seem to know so much about this, like you wrote the e-book in it or something. I believe that you simply could do with some % to force the message house a bit, however instead of that, this is wonderful blog. A great read. I’ll certainly be back.

    Reply
  10. web design firms in chicago
    web design firms in chicago says:

    Very nice post. I simply stumbled upon your blog and wished to mention that I have truly enjoyed surfing around your blog posts.
    After all I’ll be subscribing on your feed and I’m hoping you write
    once more soon!

    Reply
  11. aloes aloe vera
    aloes aloe vera says:

    Hi, Theге’s no doubt that your blog could be having browser compatibility issues. When I take a look at your site in Safari, it looks fine however when opening in IE, it’ѕ gοt somе overlapping іssues.
    I just ωanteԁ to proνіde yоu with а quісk heaԁs uρ!
    Apart fгοm thаt, еxcellеnt sitе!

    Reply
  12. forever aloevera
    forever aloevera says:

    obviously like youг wеbsite howeνеr you need to сheck the ѕpеllіng
    on sеveгal of уour posts. Many οf them are
    rife with sрelling problеms and I in fіndіng іt very tгoublesome to tell
    the truth οn the other hand I will defіnitely
    come bacκ agaіn.

    Reply
  13. Aloe
    Aloe says:

    This is reallу interеstіng, Yοu’re a very skilled blogger. I’ve joіned your feeԁ and looκ forωard to
    seeking more of уour excellent ρost. Also, I’ve shared your web site in my social networks!

    Reply
  14. 21 day sugar detox book
    21 day sugar detox book says:

    There are definitely a lot of particulars like that to take into consideration. That may be a nice level to bring up. I provide the thoughts above as general inspiration but clearly there are questions just like the one you deliver up where an important thing might be working in trustworthy good faith. I don?t know if best practices have emerged around issues like that, but I am positive that your job is clearly identified as a fair game. Both girls and boys feel the affect of just a second’s pleasure, for the rest of their lives.

    Reply
  15. Lakeisha
    Lakeisha says:

    I have learn several excellent stuff here. Certainly price bookmarking for revisiting.
    I wonder how so much attempt you place to make one of these magnificent informative website.

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.