以下是我的数据结构的样子
Controller
API
V1
Controller1.rb
Controller2.rb
Serializers
Model1Serializer.rb
Model2Serializer.rb
我试图访问控制器中的序列化程序
这是我的控制器
class API::V1::Controller1 < ApplicationController
require_relative 'model1_serializer'
def doStuff
render json:MyData, each_serializer:Model1Serializer
end
end
这是我的序列化程序
class API::V1::Serializers::Model1Serializer < ActiveModel::Serializer
# Code here for serializing
end
我收到以下错误消息。为什么认为Model1Serializer属于Controller 1?
未初始化的常量API :: V1 :: Controller1 :: Model1Serializer
如果在我的控制器中我将Model1Serializer
更改为API::V1::Serializers::Model1Serializer
然后它可以正常工作,除非我不想依赖我的命名空间中的V1,这样如果我决定移动代码到V2我不会改变代码指向V2。处理此问题的最佳方法是什么?
答案 0 :(得分:3)
&#34;为什么认为Model1Serializer在Controller 1之下:
严格来说,事实并非如此。查找常量时,Ruby会检查多个名称空间(如果可用),但错误消息只提到最内层名称空间。
为什么在引用类时会出现“未初始化的常量”错误?
要回答这个问题,了解Ruby如何查找常量非常重要。假设您有此命名空间层次结构:
module API
module V1
class Controller1
end
end
end
如果您从Model1Serializer
访问Controller1
,Ruby会检查以下嵌套命名空间:
API::VI::Controller1::Model1Serializer
API::VI::Model1Serializer
API::Model1Serializer
::Model1Serializer
但Model1Serializer
中定义的API::VI::Serializers::Model1Serializer
未包含在此列表中。这就是Ruby无法找到它的原因。
要解决此问题,您应该更改有问题的行以包含子模块:
render json: MyData, each_serializer: Serializers::Model1Serializer
但很可能它仍然无法工作,因为你正在使用&#34;快捷命名空间&#34;,即API::V1
而不是module API; module V1; ...; end; end
这会阻止Ruby搜索父命名空间,因为它们未添加到嵌套模块列表中。
换句话说,Ruby只检查以下命名空间:
API::VI::Controller1::Serializers::Model1Serializer
::Serializers::Model1Serializer
您可以通过在所需的代码位置调用Module.nesting
来访问模块层次结构。
免责声明:Ruby常量查找比此处介绍的要多得多。
答案 1 :(得分:1)
您的控制器为API::V1::Controller1
,但您的序列化程序为API::V1::Serializers::Model1Serializer
。
在doStuff
方法中,您尝试查找Model1Serializer
- 但在命名空间中无法从此处查看该类。
尝试使用API::V1::Serializers::Model1Serializer
代替。
更新: OP编辑了他的问题:
如果在我的控制器中我将Model1Serializer更改为API :: V1 :: Serializers :: Model1Serializer然后它可以工作,除了我不想依赖于y命名空间中的Vq,这样如果我决定移动到V2的代码我不会最终改变代码指向V2。处理此问题的最佳方法是什么?
快速方法是在API模块中定义Current = V1
,然后在从控制器引用模型时引用API::Current::...
。
更好的方法是仔细考虑为什么需要在同一个应用程序中同时提供多个API,以及这是否真的是对它进行版本化的正确方法。 (但这可能超出了单个SO答案的范围,而且过于依赖于您的具体应用。)