пространство имен rails 4: модели и контроллеры структуры папок
Моя текущая структура приложения выглядит следующим образом:
Пример контроллера выглядит так:
class Api::V1::RegisterController < Api::V1::ApiController
def create
@user = ::V1::User.new(user_params)
@user.email_address = params[:email_address]
@user.age_verification = params[:age_verification]
@user.remote_addr = request.env['REMOTE_ADDR']
@user.web_browser = browser.name.to_s + "(" + browser.version.to_s + ")"
@user.operating_system = browser.platform.to_s
if @user.save
head status: 201
else
render_bad_request(@user.errors.messages)
end
end
private
def user_params
params.permit(:email_address, :remote_addr, :web_browser, :operating_system, :age_verification)
end
end
Пример модели выглядит следующим образом:
class V1::User < ActiveRecord::Base
validates_presence_of :remote_addr, :web_browser,
:operating_system, :age_verification, :email_address
validates :email_address, uniqueness: { case_sensitive: false },
email_format: { check_mx: true }
end
Мой основной вопрос здесь заключается в том, почему я вынужден использовать ::V1
перед моими моделями? Есть ли лучший способ обойти это, или я что-то упускаю?
2 ответа:
Постоянные поисковые запросы выполняют поиск в текущей области модуля, а затем перемещаются вверх по дереву вложенности модуля. Если вы просто используете
V1::User
, то код вRegisterController
будет искать сначала вApi::V1::RegisterController
дляV1
, затем, не найдя его, переместится доApi::V1
, а затем доApi
, где он находитV1
, поэтому он успешно нашел константуV1
. НоApi::V1
не содержит константы с именемUser
(или, по крайней мере, не той, о которой вы думаете). Если поместить::
впереди, то постоянный поиск начинается в верхней части модуля. пространство имен, более или менее.Что касается того, есть ли лучший способ... возможно, вы хотите поменять местами уровни
V1
сApi
? Тогда был бы модуль управления версиями верхнего уровня, иV1::Api::WhateverController
мог бы найтиUser
без указания версии. Если это то, чего вы пытаетесь достичь....
В этом примере
::V1
и::Api::V1
являются отдельными объектами модуля. Когда вы ссылаетесь наV1::User
изнутриApi::V1::ApiController
, ruby будет искать в пределах ближайшегоV1
модуль дляUser
. Поскольку вы уже находитесь внутриAPI::V1
, ruby затем пытается ссылаться на::Api::V1::User
. Когда он не может найти его, включается автопогрузчик ActiveSupport и ищетapi/v1/user.rb
где-то в пути загрузки. Поскольку такого файла не существует, автозагрузчик не может найти модельUser
и выбрасываетсяNameError
.