My new rails application won’t display the “Yay!” page!

I was doing some recent environment testing with rails with the same application created on each of OSX, CentOS, and Ubuntu and was surprised when the application gave an error about no root route available, instead of the “Yay!” page:


I, [2020-02-12T16:51:06.845723 #46720] INFO -- : [8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] Started GET "/" for 127.0.0.1 at 2020-02-12 16:51:06 -0800
F, [2020-02-12T16:51:06.846251 #46720] FATAL -- : [8d1ab83a-b4e4-45bf-a734-a6494c4d15c2]
F, [2020-02-12T16:51:06.846316 #46720] FATAL -- : [8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] ActionController::RoutingError (No route matches [GET] "/"):
F, [2020-02-12T16:51:06.846353 #46720] FATAL -- : [8d1ab83a-b4e4-45bf-a734-a6494c4d15c2]
F, [2020-02-12T16:51:06.846390 #46720] FATAL -- : [8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] actionpack (5.2.4.1) lib/action_dispatch/middleware/debug_exceptions.rb:65:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] actionpack (5.2.4.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] railties (5.2.4.1) lib/rails/rack/logger.rb:38:in `call_app'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] railties (5.2.4.1) lib/rails/rack/logger.rb:26:in `block in call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] activesupport (5.2.4.1) lib/active_support/tagged_logging.rb:71:in `block in tagged'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] activesupport (5.2.4.1) lib/active_support/tagged_logging.rb:28:in `tagged'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] activesupport (5.2.4.1) lib/active_support/tagged_logging.rb:71:in `tagged'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] railties (5.2.4.1) lib/rails/rack/logger.rb:26:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] actionpack (5.2.4.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] actionpack (5.2.4.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] rack (2.2.2) lib/rack/method_override.rb:24:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] rack (2.2.2) lib/rack/runtime.rb:22:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] activesupport (5.2.4.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] actionpack (5.2.4.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] rack (2.2.2) lib/rack/sendfile.rb:110:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] railties (5.2.4.1) lib/rails/engine.rb:524:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] puma (3.12.2) lib/puma/configuration.rb:227:in `call'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] puma (3.12.2) lib/puma/server.rb:674:in `handle_request'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] puma (3.12.2) lib/puma/server.rb:476:in `process_client'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] puma (3.12.2) lib/puma/server.rb:334:in `block in run'
[8d1ab83a-b4e4-45bf-a734-a6494c4d15c2] puma (3.12.2) lib/puma/thread_pool.rb:135:in `block in spawn_thread'

I had assumed that any new rails application would serve out the, every so happy, “Yay!” page, regardless of environment. It turns out not to be the case. To fix the issue, set the RAILS_ENV to development and restart the rails server:


> RAILS_ENV=development rails server
=> Booting Puma
=> Rails 5.2.4.1 application starting in development
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.2 (ruby 2.6.0-p0), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop

Easy fix!

Rails new fails to create all of the content…

I recently deployed a Rails app on a CentOS 8 container and was surprised to see that the ‘rails new’ command did not create the entire application directory structure that I would expect, ie:

[root@607ebc931c48 app]# rails _5.2.3_ new centos_app_2
      create
      create  README.md
      create  Rakefile
      create  .ruby-version
      create  config.ru
      create  .gitignore
      create  Gemfile
         run  git init from "."

I didn’t know that git was a requirement now for rails apps, so the issue was resolved by installing the git client.

# dnf install -y git

To get a rails application created using a CentOS 8 docker container, use the following steps. This will assume rails 5.2.3 and ruby 2.6.3:

docker run -i -t --rm -v ${PWD}:/usr/src/app centos:8 bash
dnf install curl git gnupg2 which -y
gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable
source /etc/profile.d/rvm.sh
rvm requirements
rvm install 2.6.3
gem install rails -v 5.2.3
rails _5.2.3_ new centos_app

Note that the container actually takes quite a bit to build, so making an image would be more useful as subsequent rails commands could be run more easily.

Why is rails 5.2 joining to the same table twice?

I was working on a Rails project for a client recently where I was trying to figure out why a model search operation was joining to the same table twice, resulting in a huge performance hit. The answer turned out to be an incomplete understanding of the ‘has_many’ ‘:through’ relationship.

Given a model with the following relationships (using the rails documentation example):

class Physician < ApplicationRecord
  has_many :appointments
  has_many :patients, through: :appointments
  ...
end

I added a search method to return results based on web form input of a begin timestamp, end timestamp, and search term. I am also using the will_paginate gem. Also, my dataset is large enough that I do not want to return results without input parameters:

  def self.search(search, current_page, begin_timestamp, end_timestamp)
    if search
      if search.length > 0 
        Physician.includes(:patients, :appointments).where('patients.updated_at BETWEEN ? AND ?  and patients.name LIKE ?', "#{begin_timestamp}", "#{end_timestamp}", "%#{search}%").references(:patients, :appointments).paginate(page: current_page, per_page: 15).order('patients.name ASC').distinct
      end 
    end 
  end 

This resulted in a query (as seen in the mysql console and the rails application logs) that joined to the appointments table twice. Once for the has_many, through association, and once for the includes, references as added to the model.

The answer ended up being to remove the reference to appointments in the Physician model.

  def self.search(search, current_page, begin_timestamp, end_timestamp)
    if search
      if search.length > 0 
        Physician.includes(:patients).where('patients.updated_at BETWEEN ? AND ?  and patients.name LIKE ?', "#{begin_timestamp}", "#{end_timestamp}", "%#{search}%").references(:patients).paginate(page: current_page, per_page: 15).order('patients.name ASC').distinct
      end 
    end 
  end 

This optimization increased performance by a huge margin. The application is now usable.

Rails timestamp search using datetime_field_tag

I recently worked on an issue when creating a Rails form to search and display objects by timestamp and spent far too much time troubleshooting an issue with the datetime_field_tag form helper.

The issue began with the following two lines in my view:

    <%= datetime_field_tag(:begin_timestamp, params[:begin_timestamp]) %>
    <%= datetime_field_tag(:end_timestamp,   params[:end_timestamp]) %>

Evidently, you cannot place more than one space between the name assigned to the form helper and the value to populate in the form helper. The above two lines don’t format well in this wordpress blog post, but there are 3 spaces between ‘:end_timestamp’ and ‘params[:end_timestamp]’. The parameter was passed to the controller, and the code worked, but it would not display the current selection in the datetime_field_tag on submit.

The fix was to remove the additional formatting spaces, ie:

    <%= datetime_field_tag(:begin_timestamp, params[:begin_timestamp]) %>
    <%= datetime_field_tag(:end_timestamp, params[:end_timestamp]) %>

Hope this helps somebody. I spent far too much time on this.

More info:

> rails server
=> Booting Puma
=> Rails 5.2.3 application starting in production
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.6.0-p0), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: production
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop