Fun With Ruby on Rails

For the past few months I’ve immersed myself into the JavaScript/React/Redux world and even turned a bit into a JavaScript fanboy. However, I recently had the opportunity to take a break from JavaScript and built a vanilla Ruby On Rails app, and I rediscovered the speed, simplicity, and fun of building with Rails. I came across some extra fun Rails helper methods, tips, and tricks and I want to share because we all deserve a little more joy in this world, amirite?

Rails helper: time_ago_in_words

The Rails ActionView date helper time_ago_in_words takes an argument, for example, Time.now and outputs elapsed time since the input in prose. How fun is that?!

Some examples from the documentation:

1
2
3
4
5
6
7
8
9
10
11
time_ago_in_words(3.minutes.from_now) # => 3 minutes
time_ago_in_words(3.minutes.ago) # => 3 minutes
time_ago_in_words(Time.now - 15.hours) # => about 15 hours
time_ago_in_words(Time.now) # => less than a minute
time_ago_in_words(Time.now, include_seconds: true) # => less than 5 seconds
from_time = Time.now - 3.days - 14.minutes - 25.seconds
time_ago_in_words(from_time) # => 3 days
from_time = (3.days + 14.minutes + 25.seconds).ago
time_ago_in_words(from_time) # => 3 days

An alias for the time_ago_in_words method is distance_of_time_in_words_to_now.

Rails helper: to_sentence

The Rails helper to_sentence takes an array and converts it to a comma separated sentence, where the last element is joined by a connector word, for example:

1
2
3
4
5
6
7
8
9
10
[].to_sentence # => ""
['one'].to_sentence # => "one"
['one', 'two'].to_sentence # => "one and two"
['one', 'two', 'three'].to_sentence # => "one, two, and three"
['one', 'two'].to_sentence(two_words_connector: '-')
# => "one-two"
['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
# => "one or two or at least three"

Joyous! Here’s the documentation.

Rails helper: div_for

The helper div_for works very similarly to form_for but is specifically for divs. Div_for creates a div element with an id and class parameters that reference the specified Active Record object. Particularly useful if you want to iterate through a collection of divs.

Here’s a quick example:

1
2
3
<%= div_for(@article, class: "frontpage") do %>
<td><%= @article.title %></td>
<% end %>

Note: With Rails 5, div_for was removed from core Rails and moved to the record_tag_helper gem.

Rails migrations: t.belongs_to in table migration

Did you know that you can include belongs_to in your table migrations?

By including belongs_to in your migration, the Rails generator knows to add the corresponding belongs_to in the object model.

In the following example…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.belongs_to :category
t.string :name
t.decimal :price
t.text :description
t.timestamps
end
end
def self.down
drop_table :products
end
end

… including t.belongs_to :category produces the corresponding model:

1
2
3
class Product < ActiveRecord::Base
belongs_to :category
end

Rad.

Adding belongs_to in your table migrations is also an alias for t.references. Read more about Rails associations here.

Rails migrations: def up / def down vs. def change

You may have noticed in the example above that Ryan Bates is using def up and def down vs. def change.

In most cases, Rails can guess the reverse of your migration, for example, create_table and drop_table, and add_column and remove_column. There, writing your migrations with def change makes sense and Rails will know the reverse and execute it on rails db:rollback. See the Rails guide on using the change method for a list of all supported migration definitions.

However, in cases where Rails can’t automatically match the reverse action, be specific and write separate up and down migration definitions.

For example, if you wanted to change the precision of a decimal point in your database, Rails couldn’t automatically guess the original precision on rollback, and separate up/down migration definitions are required. Here’s the code:

1
2
3
4
5
6
7
8
9
class AddDetailsToProducts < ActiveRecord::Migration
def self.up
change_column :products, :price, :decimal, precision: 10, scale: 2
end
def self.down
change_column :products, :price, :decimal, precision: 5, scale: 2
end
end

Rails routes: resource vs. resources

Lastly, you may have seen routes defined with resources, but there’s also an option called resource. The difference is subtle but an important semantic one that signals to other developers your intent and what they can expect from the application.

You would use the singular resource to indicate that only a single resource will ever exist, for example a user dashboard. Two differences in behavior to note with the singular resource:

  1. resource does not define routes with an id, since a singular resource does not need serialized ids
  2. singular resources still map to plural controllers

Below is an example of routes with a singular resource adapted from the Rails guide on singular resources:

HTTP Verb Path Controller#Action Used for
GET /dashboard/new dashboards#new return an HTML form for creating the dashboard
POST /dashboard dashboards#create create the new dashboard
GET /dashboard dashboards#show display the one and only dashboard resource
GET /dashboard/edit dashboards#edit return an HTML form for editing the dashboard
PATCH/PUT /dashboard dashboards#update update the one and only dashboard resource
DELETE /dashboard dashboards#destroy delete the dashboard resource

Powered by Hexo and Hexo-theme-hiker

Copyright © 2016 - 2017 Adventures In Coding & Algorithms All Rights Reserved.

© Christina Entcheva 2016