The Rails 5.1 beta was released just a few weeks ago, and lots of great features and functionalities are added since rails 5.
This is first part of two part series on new significant features in rails 5.1 beta and 5. To dive deep into rails 5 specific features, checkout Rails 5: Not just ActionCable.
To start using latest rails 5.1.0.beta1 you can install it with:
gem install rails — pre
Check current version of rails with using following command:
rails -v> Rails 5.1.0.beta1
Now using `rails new` will create a ruby on rails application with latest pre-release version.
Also, you can use older versions of rails along with rails 5 for your existing and new applications that need to be created with older versions of rails.
To use the previous version for creating new rails application you can:
# following command will list installed gem with versions for rails
gem list | grep rails
# my local shows following rails versions installed
> rails (5.1.0.beta1, 5.0.2, 5.0.1, 4.2.8, 4.2.7.1, 4.2.7)
# To create rails application using version 4.2.7.1,
rails _4.2.7.1_ new my-app
Let’s talk about some exciting new features in rails 5.1 beta:
Your secrets are safe with Rails
Rails 5.1 introduces encrypted secrets. You no longer need to worry about accidently checking out app specific secret credentials into version control. I prefer to store sensitive secrets such as AWS keys into environment variables and refer them through secrets.yml or aws.yml for aws specific credentials.
With encrypted secrets, the secrets file will be encrypted and can be checked in to version control without any worry!
One thing to remember here is that our secrets.yml will behave exactly the same as it did previously, but we will have one new file called secrets.yml.enc, in which encrypted secrets are stored.
To get started with this, first run following command:
rails secrets:setup
This will generate new secrets.yml.enc and secrets.yml.key. Apart from this, above line also adds ‘config/secrets.yml.key’ to our file.
We can remove this private key file and store it to RAILS_MASTER_KEY environment variable.
To edit our new secrets.yml.enc file:
EDITOR=nano rails secrets:edit
Optionally, by setting environment variable EDITOR with your favorite editor such as nano or vim, you can skip writing EDITOR=nano every time you need to edit secrets file:
rails secrets:edit
Above command decrypts secrets.yml.enc and after you exit code editor, it encrypts secrets.yml.enc with a private key set in secrets.yml.key or from environment variable RAILS_MASTER_KEY.
However, these secrets stored in new secrets.yml.enc file are not enableed by default. You need to enable them by allowing to read encrypted secrets as shown below:
Rails.application.configure do
...
config.read_encrypted_secrets = true
end
This new feature doesn’t stop you from using old secrets.yml, it works exactly as it worked before. It would be better to use new secrets.yml.enc instead of sensitive information.
Parameterized Mailers
Mailers are starting to look more like controllers after this feature. This new API lets you share parameters and common logic across different mailer actions seamlessly. Before action and after action hooks for mailers now allows sharing of params and common behavior across mailer actions.
For instance, UserMailer with welcome and sign_up actions looked like as below:
class UserMailer < ApplicationMailer
default from: "support@example.com"
def welcome(email, name, message)
@email = email
@name = name
@message = message
mail to: @email, subject: "Welcome to Example."
end
def sign_up(email, name, message)
@email = email
@name = name
@message = message
mail to: @email, subject: "Confirm your email!"
end
end
And this actions of mailer can be called with parameters passed as:
UserMailer.welcome("xyz@gmail.com", "xyz", "some message").deliver_later
With new parameterized mailers in rails 5.1 UserMailer can be rewritten as:
class UserMailer < ApplicationMailer
before_action {
@email = params[:email]
@name = params[:name]
@message = params[:message]
}
default to: -> { @email },
from: -> { "support@example.com" }
def sign_up
mail subject: "Confirm your email!"
end
def welcome
mail subject: "Welcome to Example."
end
end
And this actions of mailer can be called with new syntax as:
UserMailer.with(email: "xyz@gmail.com", name: "xyz", message: "some message").welcome.deliver_later
This way, parameters can be used to extract common behavior among different mailer actions. Haven’t played with this much, but seems like it’s a better improvement. This feature is backward compatible, which means old syntax will still work.
Unify form_tag/form_for with form_with
Rails give two different types of form builders form_tag and form_for which does almost the same thing. A common convention is to use form_for when you need to save data to model as it magically creates form specific to model with url and actions for that model. form_tag is used to create a generic form, when sending data to model is not the only goal.
To state this in simple words, For user sign_up process you should use form_for as data entered needs to be stored in the User model. Bur for user sign_in, you should be using form_tag as you are not generating, saving or updating data for the user in that matter.
But it took me some time to learn the difference between two, and good thing is that form_tag and form_for are unified into form_with.
Suppose you have two models Category and SubCategory and you want to add a new category with a related subcategory, your form in rails 4 might have looked something like this:
<%= form_for(@category) do |f| %>
<% if f.object.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(f.object.errors.count, "error") %> prohibited this category from being saved:</h2>
<ul>
<% f.object.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<%= f.fields_for :sub_categories do |sub_cat_form| %>
<div class="field">
<%= sub_cat_form.label "sub_category name" %>
<%= sub_cat_form.text_field :name %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The same thing can be done with form_with:
# we are saving data to category and subcategory models
<%= form_with(model: @category) do |f| %>
# instead, we can simply pass url, along with scopes if necessary
# <%= form_with(scope: :category, url: category_path) %>
<% if f.object.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(f.object.errors.count, "error") %> prohibited this category from being saved:</h2>
<ul>
<% f.object.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<%= f.fields(:sub_categories) do |sub_cat_form| %>
<div class="field">
<%= sub_cat_form.label "sub_category name" %>
<%= sub_cat_form.text_field :name %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
form_for and form_tag can be used as they were used in rails 5.x and will be soft-deprecated with warnings in rails 6.x.
For 5.x, form_for and form_tag should just be soft deprecations, no warnings. Then we can deprecate with a warning, perhaps, in Rails 6.x.
You can read more about form_with in discussion: https://github.com/rails/rails/issues/25197
New Rails loves Javascript:
For javascript, you can either love it or hate it; but you just can’t ignore it, or say live without it. One can not imagine today’s web development without javascript.
As mentioned in ruby weblog, three major changes were made for javascript:
Yarn:
This is basically bundler-like solution used heavily in Javascript to manage different versions and dependencies.
From Yarn documentation:
Yarn is a package manager for your code. It allows you to use and share code with other developers from around the world. Yarn does this quickly, securely, and reliably so you don’t ever have to worry.
And from Ruby weblog:
Every dependency specified via yarn is made available to be required in the asset pipeline, just like vendored dependencies would have been.
Webpack support:
Webpack is also the package manager for Javascript, and is used by wide range of front-end developers. You can choose to use webpack by adding ` — webpacker` option with rails new. Apart from that, you can use webpack with webpacker gem. Webpacker will be used with yarn and is fully compatible with asset pipeline.
Rails provides flexibility to choose webpacker along with yarn.
This is fully compatible with the asset pipeline, which you can continue to use for images, fonts, sounds, whatever. You can even have some JavaScript on the asset pipeline and some done via Webpack.
jQuery doesn’t need to be added by default:
Rails doesn’t require jQuery to provide features like data-remote, data-confirm, and the other parts of Rails UJS. Hence, jQuery is not added as default dependency anymore. It is made optional.
If you don’t have much experience with Javascript, or are not familiar with webpack and yarn, I would recommend reading this article Embracing Change: Rails 5.1 Adopts Yarn, Webpack, and the JS Ecosystem where Samuel Mullen explains this well.
TL;DR:
Rails 5.1 works seamlessly with the changing the ecosystem of Javascript. New simplified form_with, parameterized mailers and secure secrets make the rails framework more mature and easy to work with. Apart from these features, direct and resolved routes are also going to be very helpful.
Checkout part 2 of this article series: Rails 5: Not just ActionCable
Feel free to talk about the features you are excited about in Rails 5.1 and share ❤ the article.
About Solute TechnoLabs
We are a bunch of passionate technocrats who love building products and applications that we take pride in. Our mobile and web applications have been downloaded and used by millions and we’re here to change the internet: One piece at a time!