不可算名詞をモデルやテーブルに使う場合の注意点
不可算名詞をモデルやテーブルに使う場合の注意点
アプリケーション開発中にモデル名やテーブル名に不可算名詞を使う機会があり、そこで少しハマったのでこちらに対処方法をまとめます。
[fish]というモデル名で[fishes]というテーブル名を付けたい場合に、モデルファイルとスキーマファイルを以下のようにしました。
[app/models/fish.rb] class Fish < ApplicationRecord end
[db/schema.rb] create_table "fishes", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "kind", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.index ["kind"], name: "index_fishes_on_kind", unique: true end
[rails c]でFishモデルを使おうとすると以下のようなエラーになってしまいました。
$ rails c Loading development environment (Rails 6.0.4.1) irb(main):001:0> Fish.all Fish Load (0.4ms) SELECT `fish`.* FROM `fish` LIMIT 11 Traceback (most recent call last): ActiveRecord::StatementInvalid (Mysql2::Error: Table 'fishing_cooking_development.fish' doesn't exist)
fishテーブルがありませんとなってしまいます。
スキーマファイルに[fishes]と記載しており、Mysqlにも[fishes]テーブルがあるのに、なぜか[fish]テーブルを使おうとする。。。
これは、railsがモデル名から使用するテーブル名を予測していることによる原因でした。
通常railsは、モデル名を単数系で記述してテーブル名を複数形で記述することにより、使うテーブルをrailsが予測してくれますが、今回のように[fish]という不可算名詞を使用すると、railsは、テーブル名も[fish]というテーブル名を使用しようとします。
[fish]の場合は、1種類の魚がたくさんいる場合は複数形も[fish]になりますが、たくさんの種類の魚という場合には、複数形は[fishes]となります。
上記のことからrailsは、[fish]の複数形は[fish]と解釈して[fish]というテーブルを使おうとしていました。
railsの複数形、単数系の判断は以下のコマンドで調べることができます
irb(main):001:0> "fish".pluralize #[fish]の複数形を調べる => "fish" irb(main):002:0> "fishes".singularize #[fishes]の単数系を調べる => "fish"
今回のようにモデル名を[fish]でテーブル名を[fishes]にしたい場合は、以下のように設定することでイレギュラー設定をすることができます。
ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.irregular 'fish', 'fishes' end
上記を記述後に再度railsの単数系と複数形の判断を確認すると以下のようになります。
irb(main):001:0> "fish".pluralize => "fishes" irb(main):002:0> "fishes".singularize => "fish"
irb(main):003:0> Fish.all Fish Load (1.8ms) SELECT `fishes`.* FROM `fishes` LIMIT 11 => #<ActiveRecord::Relation []>
上記のようにFishのActiveRecordも使えるようになりました。