Rails 6 unnoticed features

February 15, 2019 – Alexandre Ferraille – 6-minute read

This article was written before Drivy was acquired by Getaround, and became Getaround EU. Some references to Drivy may therefore remain in the post

Rails 6.0.0.beta1 is out and you may have already tested it. We all have heard about the main features such as multi-database connectivity, Action Mailbox & Action Text merge, parallelized testing, Action Cable testing etc. But there’s also a ton of other cool features that I found interesting.

Requirements change

With each major release comes new requirements, starting with Ruby which is now required with a minimal version of 2.5.0 instead of 2.2.2 for Rails 5.2. Our databases also get an upgrade with 5.5.8 for MySQL, 9.3 for PostgreSQL and 3.8 for SQLite.

Webpacker as default

Webpacker has been merged in Rails 5.1 and provides a modern asset pipeline with the integration of Webpack for your javascript files. Before Rails 6 you had to generate your app with the --webpacker option to use it, now Webpacker is the default and it’s a good first step for a modern asset pipeline on Rails in replacement of Sprockets - you currently still need it to load your CSS and images.

Environment support for encrypted credentials

Rails 5.1 introduced encrypted credentials: a file containing your passwords, API keys etc., which can be safely shared. All you need to do is to store safely the ENV[’RAILS_MASTER_KEY’]. This created a problem: when you wanted to have different credentials for your environments you were stuck with one shared file across all your environments. This is solved now: you can have a specific encrypted file per environment.

DNS Guard: hosts whitelist

Rails 6 added a new middleware called ActionDispatch::HostAuthorization allowing you to whitelist some hosts for your application and preventing Host header attacks. You can easily configure it with a String, IPAddr, Proc and RegExp (useful when dealing with wildcard domains).

Translations and _html

If you’re using the _html suffix a lot for your translation keys, you can refactor a group of keys on the same level by adding _html to the parent and removing it to the children.

Filtering sensitive parameters

If you’re dealing with sensitive data you want to hide from logs, console etc. you can configure ActiveRecord::Base::filter_attributes with a list of String and RegExp which match sensitive attributes.

Time comparisons

Date, DateTime and Time received a bunch of methods allowing us to do comparisons without traditional operators - easier to read:

rental_1.starts_at.after? rental_2.ends_at # => true
rental_1.starts_at.before? rental_2.ends_at # => false

Private delegate

You can now delegate a method without exposing it publicly with the new option private.

delegate :full_name, to: :current_user, private: true

Relation#pick

If you need to select a column from an ActiveRecord::Relation you can use pluck which will trigger the following query:

SELECT `articles`.`title` FROM `articles`

But if you want the first value you’ll need to add a .limit(1), that’s what pick is doing for you:

SELECT `articles`.`title` FROM `articles` LIMIT 1

Deprecate update_attributes! & update_attributes

Should we prefer update_attributes or update? update_attributes! or update!? These methods have always been confusing but were nothing more than aliases. No more confusions and consistency issues!

Utf8mb4 as default for MySQL

Users are putting emojis 😀 everywhere, I’m 💯% sure you already got the issue when trying to insert them in your database. Setting Utf8mb4 as default instead of Utf8 solves the problem. It also helps if you need to handle Asian characters, mathematical characters etc. Note that you still need to migrate your old tables manually.

Change system database

Changing database from default SQLite to PostgreSQL (for example) is something that you might need to do at an early stage of your project, and could be painful if you don’t have the proper config files and templates in your Rails app. Now, you no longer need to generate a new Rails app with the proper database to grab the files you need, rails db:system:change is here.

create_table: :if_not_exist option for migrations

When running, rollbacking and updating migrations it can be a mess and sometimes you need to manually clean your database in order to run a create_table which already physically exists. Now, you can bypass a create_table block in this case using :if_not_exist option.

Using and navigating in the session object can be painful if the keys/sub-keys you’re looking for are not defined. Fortunately, Rails 6 is adding a Hash-like method called dig, allowing you to safely navigate in your session object.

Enumerable#index_with

New method allowing you to create a Hash from an Enumerable:

%w(driver owner drivy).index_with(nil)
# => { 'driver' => nil, 'owner' => nil, 'drivy' => nil }

%w(driver owner drivy).index_with { |role| delta_amount_for(role) }
# => { 'driver' => '...', 'owner' => '...', 'drivy' => '...' }

Array#extract!

This is a new method added to Array which works like reject! but instead of returning an array of the non-rejected values, you get the values which returns true for the block.

my_array = [1,2,3,4]
my_array.extract! { |v| v > 2 } # => [3,4]
my_array == [1,2] # => true

Starting your app

You get an error when starting your rails server? The rails server command no longer passes the server name as a Rack argument but is using -u option. You will start you server this way: rails server -u puma.

Of course, there’s more

This is a non-exhaustive list of things I found fun and/or useful and I encourage you to read the full changelog. A lot of deprecation has been added, previously deprecated methods have been dropped and there’s much more that you might find useful.

Did you enjoy this post? Join Getaround's engineering team!
View openings