ActiveRecordのカラム名を大文字にすると躓く

Railsでモデルを作成する場合、テーブルのカラム名を大文字にしてしまうと
動かないわけではありませんが、定数と判断されるようで挙動が変わる点がありました。

小文字で作った場合

まずbookモデルを作る

rails g model Book title:string

マイグレーションでテーブルを作成

rails db:migrate

モデルにtitleを表示するだけのメソッドを追加

book.rb
class Book < ApplicationRecord
  def print_title
    p title
  end
end

コンソールで動作確認します。

irb(main):007:0> book = Book.new title: "hoge-book"
=> #<Book id: nil, title: "hoge-book", created_at: nil, updated_at: nil>
irb(main):008:0> book.print_title
"hoge-book"
=> "hoge-book"
irb(main):009:0> book.title
=> "hoge-book"

なんも問題ないですね

大文字で作った場合

bookモデルを作りますがカラムを大文字にします。

rails g model Book Title:string

マイグレーションでテーブルを作成

rails db:migrate

モデルにTitleを表示するだけのメソッドを追加

book.rb
class Book < ApplicationRecord
  def print_title
    p Title
  end
end

コンソールで動作確認します。

irb(main):003:0> book = Book.new Title: "hoge-book"
=> #<Book id: nil, Title: "hoge-book", created_at: nil, updated_at: nil>
irb(main):004:0> book.print_title
NameError: uninitialized constant Book::Title
        from app/models/book.rb:4:in `print_title'
        from (irb):4
irb(main):005:0> book.Title
=> "hoge-book"

book.Titleは問題なく呼び出せましたが、book.print_titleはエラーになりました。

カラムを定義するとActiveRecordがカラム名に対応したメソッドを定義するようで
小文字の場合はtitle、大文字の場合はTitleというメソッドがそれぞれ存在します。
インスタンスメソッド内からそれらを呼び出そうとした時、小文字の場合は変数もしくはメソッドを探しに行きますが
大文字の場合は定数を探しにいってしまい、Titleというメソッドが存在いていてもNameError: uninitialized constant Book::Titleとなってしまいます。

また、self.をつけて明示してあげると参照できるようになります。

book.rb
class Book < ApplicationRecord
  def print_title
    p self.Title
  end
end
irb(main):002:0> book.print_title
"hoge-book"
=> "hoge-book"

Squeelもコケる

Squeelでも以下のようにするとNameError: uninitialized constant Book::Titleとなります。

Book.where { Title.like "#{value}%" }

標準のやり方でやるしかないですね。

Book.where('Title like ?', "#{value}%")

そもそも

カラム名は小文字のスネークケースを使いましょう。
レールから外れると痛い目を見ます。

今回は既存のデータベースを利用するシーンで命名規則に沿っていなくて痛い目見ました。