我们有2个模型:估值和文件。两者都在微服务中,所以我们使用ActiveResource来访问它们。
class Valuation < ActiveResource::Base
self.site = "#{config.valuation_service.base_url}/valuations"
self.include_root_in_json = false
end
class Document < ActiveResource::Base
self.site = "#{config.valuation_service.base_url}/documents"
self.include_root_in_json = true
end
在开发中运行Rails控制台。
>> Valuation.new(documents: [{ title: 'Foo' }])
=> <Valuation:0x007f9af85f1708 @attributes={"documents"=>[#<Valuation::Document:0x007f9af85f0970 @attributes={"title"=>"Foo"}, @prefix_options={}, @persisted=false>]}, @prefix_options={}, @persisted=false>
所以文档的类名是Valuation:Document
。在生产中运行rails控制台时
>> Valuation.new(documents: [{ title: 'Foo' }])
=> <Valuation:0x007f9af595b478 @attributes={"documents"=>[#<Document:0x007f9af595a500 @attributes={"title"=>"Foo"}, @prefix_options={}, @persisted=false>]}, @prefix_options={}, @persisted=false>
该文档的类只是Document
,它尊重配置,如include_root_in_json
。
更大的问题是在对象上调用.to_json
时。
# development
>> Valuation.new(documents: [{ title: 'Foo' }]).to_json
=> "{\"documents\":[{\"title\":\"Foo\"}]}"
# production
>> Valuation.new(documents: [{ title: 'Foo' }]).to_json
=> "{\"documents\":[{\"document\":{\"title\":\"Foo\"}}]}"
我们正在使用Rails 4.2.10。
究竟是什么导致了这个?我已经检查了配置是否有任何切换开/关取决于环境但我找不到。
答案 0 :(得分:4)
ActiveResource似乎正在使用autoloading mechanism将属性名称动态转换为集合类。
因此,开发和生产之间的差异是由于急切的加载。在生产中,所有文件都是急切加载的,因此运行控制台时所有常量都已存在。
当您在开发模式下运行控制台时,ActiveResource会尝试为该属性定义类名,但该机制不适用于您的用例。
如果the constant is not found on Object
,it is created within the class that is being initialized(Valuation
)。
为了使开发以与生产相同的方式工作,您需要绕过触发此自动加载机制。这可以使用Rails中的require_dependency
方法轻松完成。
添加
require_dependency 'document'
class Valuation < ActiveResource::Base
在Valuation
课程之前,一切都应该正常工作。
此行确保在任何人尝试创建Document
类的实例之前已加载Valuation
常量,并且自动加载机制不会被使用。