1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【rails】コントローラー名やモデル名をアプリ名と同じにして痛い目見たって話

Posted at

こんばんは。

プログラミング初学者です。
現在、Ruby on Rails + Docker + MySQLでアプリの開発をしています。
そこであるエラーにハマり、数日奮闘した結果ようやく解消できたのでそのことをまとめました。

発生したエラー

バイクのレビュー投稿アプリ(名前はBIKKE)を作成しており、そのレビューの投稿画面実装のためコントローラーを下記のように記載

bikkes_controller.rb
class BikkesController < ApplicationController
  def index
    @user = User.new
  end

  def new
    @bikke = Bikke.new
  end
end

そして新規投稿画面に遷移すると、

NoMethodError!!!!!!しかもnewメソッドが!!??

Image from Gyazo

なぜ!?モデルやマイグレーションファイルの記載に間違いはなし。

まさかnewメソッドがエラーとして返されるとは、その時想像もしておりませんでした。

解消

エラー画面を見てみると、下記文面が記載されています。

undefined method 'new' for Bikke:Module

このModuleがミソですね。

つまり、このBikkeというオブジェクトがクラスではなくメソッドとして認識されている、ということを表しています。
どこかにmodule Bikkeclass Bikke::Somethingと定義されていないか確認を行いました。
※この解はTeratailにて先人エンジニアさんに教えていただきました。本当に感謝です。

module Bikkeで検索をかけると、ありました。

config/application.rb
module Bikke
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.1

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("extras")

    # Don't generate system test files.
    config.generators.system_tests = nil
  end
end

つまり、railsはrails newを行った時に、このapplication.rbでアプリ名をモジュールとして定義する仕様のようですね。

そうです。私はアプリ名とコントローラー・モデル名を同じ名前にしてしまったのです。

コントローラーやモデル名の再構築、その他ファイルの修正を行い、再度新規投稿画面に移行すると無事遷移することができました。

学び

本件では、Module Bikkeと認識されていたため、newメソッドを使えるclass Bikkeが見えなくなっていたことがエラーの原因であることがわかりました。

そもそもnewメソッドとは何か?
ActiveRecordメソッドの一つ
ActiveRecordメソッドとはモデルがテーブル操作に関して使用できるメソッドの総称である。

ここで、上記のコントローラーやモデルをReviewに変更したとしましょう。
rails cでコンソールを開き、下記コマンドを打ちます。

[1] pry(main)> Review.superclass
=> ApplicationRecord(abstract)

このReviewApplicationRecordを継承していることがわかります。
さらに下記コマンドを打ち込みます。

[2] pry(main)> ApplicationRecord.superclass
=> ActiveRecord::Base

つまりReviewはしっかりActiveRecord::Baseを継承しているからnewメソッド、そしてallメソッドfindメソッド,saveメソッドなどが使えるのですね。

ちなみに

[3] pry(main)> Bikke.superclass
NoMethodError: undefined method `superclass' for Bikke:Module

アプリ名はしっかりモジュールと定義されているため、superclassメソッドも使えないのですね。
そして、

[4] pry(main)> Module.superclass
=> Object

モジュールはオブジェクトを継承している・・・っ!

では、モジュールとクラスの違いは何なのでしょうか?

端的にいうと、

クラスはインスタンスの生成ができるのに対し、モジュールではできない。そしてクラスは継承していけるが、モジュールでは継承ができない。

厳密にはMix-inによってモジュールの機能をクラスに提供、いわば継承のようなことはできるようですが・・・。

ふんわりとした表現ですが、本件ではモジュールとクラスで継承しているものが独立しているため、使えるメソッドの違いがあり、エラーの発生に繋がったのだと考えます。
この辺はRubyの真髄でもあるのでより深ぼって理解を深めたいところですね。

兎にも角にも一度作ったコントローラーやモデルの再構築は、ER図やREADMEの変更、その他ビューファイルの調整などあらゆる部分の編集に手間がかかって疲れた・・・。
しかし、非常に良い学びとなりました。

ここまでご覧いただきありがとうございました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?