The Rails 5 Way

I started reading The Rails 5 Way recently and decided I’m going to post little snippets I want to use in the future. Hello, future me. You’re welcome. These are either:

Loading gems from GitHub

If the gem source repository is hosted on GitHub and is public, you can use the :github shorthand:

gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'

Generator Default Settings

Rails generator scripts make certain assumptions about your tool chain. Setting the correct values here means having to type fewer parameters on the command line. For instance, to use RSpec without fixtures and Haml as the template engine, our settings would look like the following:

# Configure generators values. Many other options are
# available, be sure to check the documentation.

config.generators do |g|
  g.template_engine :haml
  g.test_framework :rspec, fixture: false
end

Console

It’s possible to supply a block to console to be evaluated when the Rails environment is loaded via the terminal. This enables you to set console-specific configurations. I like saving some typing with helper methods like this one.

console do 
  def obie
    User.where(email: "obiefernandez@gmail.com").first
  end
end

Watch Rails Log Files

$ tail -f log/development.log

Named Routes in the Console

You can test named routes in the console directly using the special app object.

app.clients_path  # "/clients"
app.clients_url   # "http://www.example.com/clients"

Limiting Routes Generated

It’s possible to add :except and :only options to the call to resources in order to limit the routes generated.

resources :clients, except: [:index]
resources :clients, only: [:new, :create]

Custom Flash Types

New to Rails 4 is the capability to register your own flash types by using the new ActionController::Flash.add_flash_types macro style method.

class ApplicationController
  add_flash_types :error
end

When a flash type is registered, a special flash accessor, similar to alert and notice, becomes available to be used with redirect_to.

redirect_to post_url(@post), error: "Something went wrong!"

Boolean Conditions

It’s particularly important to take care in specifying conditions that include boolean values. Databases have various different ways of representing boolean values in columns. Some have native boolean datatypes, and others use a single character, often 1 and 0 or T and F (or even Y and N). Rails will transparently handle the data conversion issues for you if you pass a Ruby boolean object as your parameter:

Timesheet.where('submitted = ?', true)

Active Record UUID

UUIDs are becoming a popular alternative to auto-incrementing integer primary keys. (Not supported in all databases, though.)

Rails.application.config.active_record.primary_key = :uuid

Rails Migration Generator Magic

If the migration name is of the form “AddXXXToYYY” or “RemoveXXXFromYYY” and is followed by a list of column names and types then a migration containing the appropriate add_column and remove_column statements will be created.

$ rails g migration AddPartNumberToProducts part_number:string

will generate

class AddPartNumberToProducts < ActiveRecord::Migration[5.0] 
  def change
    add_column :products, :part_number, :string
  end
end

If you’d like to add an index on the new column, you can do that as well:

$ bin/rails generate migration AddPartNumberToProducts part_number:string:index

will generate

class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
  def change
    add_column :products, :part_number, :string
    add_index :products, :part_number
  end
end

The migration generator will produce join tables if “JoinTable” is part of the name.

$ rails g migration CreateJoinTableCustomerProduct customer product

will produce the following migration:

class CreateJoinTableCustomerProduct < ActiveRecord::Migration[5.0]
  def change
    create_join_table :customers, :products do |t|
      # t.index [:customer_id, :product_id]
      # t.index [:product_id, :customer_id]
    end
  end
end

Redo

It’s actually super common to forget to add something to a migration. Rails gives you rails db:migrate:redo as a convenient way to rollback and re-migrate in one command.

db:reset and db:setup

The db:setup creates the database for the current environment, loads the schema from db/schema.rb, then loads the seed data. It’s used when you’re setting up an existing project for the first time on a development workstation. The similar db:reset task does the same thing except that it drops and recreates the database first.