New Features in Rails 4.2

Rails 4.2 beta has been released and final version is going to come out soon.

Listed are some feature are going introduced in version of Rails 4.2. You can also try them while it’s beta.

  1. Active Job, ActionMailer #deliver_later

  2. Adequate records

  3. Web console

  4. Foreign key support

But apart from these there are more features which are going to ship in Rails 4.2.

Few of them are..

required option for singular associations (belongs_to and has_one)

Sometime we need to validate presence of associated object not the foreign key used to map the association

Lets say for each user there must be a account so we validate it like this –:

1
2
3
4
class User < ActiveRecord::Base
  belongs_to :account
  validates :account, presence: true
end

But in Rails 4.2 we just need to set required option to true which will validate associated object is present

1
2
3
4
class User < ActiveRecord::Base
  belongs_to :account, required: true
  has_one :profile, required: true
end

required option in generator for model and migration

When we generate model we can pass required option for references/associations

1
  rails generate model Comment commentable:references{required}

It will automatically set required true for commentable association

1
2
3
class Comment < ActiveRecord::Base
  belongs_to :commentable, required: true
end

And in migration set null: false for commentable association which is basically a database validation

1
2
3
4
5
6
7
8
9
class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.references :commentable, index: true, null: false

      t.timestamps null: false
    end
  end
end

We can also pass it with polymorphic option if we need polymorphic relation

1
rails generate model Comment commentable:references{required, polymorphic}

This required option can also be passed in generating migration

1
rails generate migration AddAccountToUsers account:references{required}

validate and validate!

validate

It runs all validations and returns true if no error found otherwise return false.

It is alias of valid? method.

validate!

It runs all validations and returns true if no error found otherwise raise ActiveRecord::RecordInvalid if any validation fails

with_options without explicit receiver

In with_options block we have to pass explicit receiver whether it is required or not

1
2
3
4
5
6
class User < ActiveRecord::Base
 with_options if: :is_admin? do |admin|
    admin.validates :name, presence: true
    admin.validates :email, presence: true
  end
end

Now in Rails 4.2 we don’t need to pass explicit receiver to with_options until it is required

1
2
3
4
5
6
class User < ActiveRecord::Base
 with_options if: :is_admin? do
    validates :name, presence: true
    validates :email, presence: true
  end
end

Touch multiple attributes

Before Rails 4.2 we can just pass one attribute in touch method

1
2
3
a = Article.first
a.touch(:published_at) # => true
a.touch(:published_at, :created_at) #=> ArgumentError: wrong number of arguments (2 for 0..1)

But in Rails 4.2 we can update multiple attributes at once with touch method

1
2
a = Article.first
a.touch(:published_at, :created_at) #=> true

Support for PostgreSQL citext data type

Rails 4.2 added support for citext column type in PostgreSQL adapter.

But we have to enable extension before running migration because its additional supplied module

1
execute "CREATE EXTENSION IF NOT EXISTS citext"

citext column type provides a case-insensitive character string type.

For example we have a users table with bio column as citext type

We have a user object with bio value as ‘developer’ but we search with ‘Developer’ it will return our user object in result

1
2
3
User.where(bio: 'Developer')
#=>SELECT "users".* FROM "users" WHERE "users"."bio" = $1  [["bio", "Developer"]]
#=> #<ActiveRecord::Relation [#<User id: 1, name: nil, email: "test@example.com", created_at: "2014-08-30 17:51:17", updated_at: "2014-08-30 17:51:17", role: nil, bio: "developer">]>

Internally citext calls lower when comparing values so we don’t need to explicitly convert value in lowercase

1
SELECT * FROM tab WHERE lower(col) = LOWER(?);

Empty your database

Rails provides us few database related rake tasks such as to create/drop database and to run migrations.

There is a new rake task added rake db:purge to empty database for current environment.

It removes your data and tables from database and of course we can pass environment RAILS_ENV like any other rake task.

New binstubs(bin/setup)

We always need some set of commands to bootstrap our application.

Now in Rails 4.2 there is default bin/setup script where we can have all tasks to setup our application in quick and consistent way. It is located in bin directory.

There are some defaults commands given by Rails but we can add more as per our requirement.

Transform Hash Values

To modify Hash values call transform_values it accepts a block and apply the block operation to each value of hash

1
2
a = {a: 1, b: 2, c: 3}
a.transform_values{ |a|a*2 } #=> {:a=>2, :b=>4, :c=>6}

There is also a bang version transform_values! which change original hash

1
2
3
a = {a: 1, b: 2, c: 3}
a.transform_values!{ |a|a*2 } #=> {:a=>2, :b=>4, :c=>6}
a #=> {:a=>2, :b=>4, :c=>6}

Truncate String by words

There is new method truncate_words which truncate a string by given number of words length

1
'This is fantastic place in this world'.truncate_words(3) #=> "This is fantastic..."

Pretty print for ActiveRecord object

Now in Rails console/logs we can print ActiveRecord object output nicely just pass that object to pp method

1
2
3
4
5
6
7
8
9
10
pp User.last

#<User:0x007f8fdf29f3a8
 id: 2,
 name: nil,
 email: nil,
 created_at: Tue, 02 Sep 2014 19:18:52 UTC +00:00,
 updated_at: Tue, 02 Sep 2014 19:18:52 UTC +00:00,
 role: "user",
 bio: nil>

Skip gems

We can skip default gems to Gem file while creating new app with --skip-gems option. They will not be added to our Gemfile

1
rails new <app name> --skip-gems turbolinks coffee-rails

References

Here are some more articles about rails 4.2

Thanks to all Rails contributors for making Rails awesome :)

If you any feedback on this article let me know @raysrashnmi on Twitter