名前空間の重複
名前空間の重なりにより、undefind method new
のエラーが出たのでその忘備録。
エラー箇所
routes.rb
Rails.application.routes.draw do
namespace :api, format: 'json' do
namespace :v1 do
resources :articles, only: %i[index show]
namespace :user do
resources :articles, only: %i[index create update destroy]
end
post 'authentication', to: 'authentication#create'
post 'registration', to: 'registration#create'
end
end
end
api/v1/registration_controller.rb
# 一部抜粋
def create
@user = User.new(user_params) #⬅️ここでエラー発生
if @user.save
json_string = UserSerializer.new(@user).serialized_json
set_access_token!(@user)
render json: json_string
else
render400(nil, @user.errors.full_messages)
end
end
恐らくnamespace
のuser
も加わり、railsがどこのuser
を呼び出しているのか分からなくなり、new
メソッドが呼び出せなくなったと思われる。
そこでこのUser
に絶対位置を指定することによってこのエラーは解決された。
User
に絶対位置を指定
api/v1/registration_controller.rb
# 一部抜粋
def create
@user = ::User.new(user_params) #⬅️ここ
if @user.save
json_string = UserSerializer.new(@user).serialized_json
set_access_token!(@user)
render json: json_string
else
render400(nil, @user.errors.full_messages)
end
end
絶対位置の指定は上記の通り、::(ダブルコロン)
を先頭につけるだけで解決した。
::
から始まる場合は一番上位の階層レベルを指すため、module内などで使う場合にモジュールの絶対的な位置を表現することができる。
この記事でわかりやすく解説している。
上記記事から抜粋
・ClassA
は相対指定、::ClassA
は絶対指定
・絶対指定は、トップレベルを指す
・::ClassA
とObject::ClassA
は同じ挙動になる
参考記事
Rubyでクラス名のはじめに::(コロンを2つ)をつけるとそのクラスの絶対的な位置表現をすることができる)
Ruby: クラス名の先頭につける :: (先頭二重コロン) は何?