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在我的模特面前使用?有没有更好的方法解决这个问题还是我错过了什么?

4

2 回答 2

3

常量查找搜索当前模块范围,然后向上移动模块嵌套树。如果你只使用V1::User,那么代码 inRegisterController将首先Api::V1::RegisterController查找 a V1,然后,如果没有找到,将向上移动到Api::V1,然后向上移动到Api它找到的位置V1,因此它成功找到了常量V1。但Api::V1不包含一个名为的常量User(或者至少不是你想的那个)。放在::前面会使常量搜索或多或少从模块命名空间的顶部开始。

至于是否有更好的方法......也许你想交换V1with的水平Api?然后会有一个顶级版本控制模块,并且V1::Api::WhateverController可以在User不指定版本的情况下找到。如果这就是你想要达到的目标......

于 2014-06-18T18:49:11.820 回答
1

在此示例中,::V1::Api::V1是单独的模块对象。当您V1::User从内部引用时Api::V1::ApiController,ruby 将在最近的 V1模块中查找User. 既然你已经在里面了API::V1,ruby 就会尝试引用::Api::V1::User. 当它找不到它时,ActiveSupport 的自动加载器会启动并api/v1/user.rb在加载路径中寻找某个位置。由于不存在此类文件,因此自动加载器无法找到User模型并NameError抛出 a。

于 2014-06-18T18:48:11.470 回答