在开发中运行rails控制台时,ActiveResource会添加一个额外的类

时间:2018-04-05 06:15:47

标签: ruby-on-rails activeresource

我们有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。

究竟是什么导致了这个?我已经检查了配置是否有任何切换开/关取决于环境但我找不到。

1 个答案:

答案 0 :(得分:4)

ActiveResource似乎正在使用autoloading mechanism将属性名称动态转换为集合类。

因此,开发和生产之间的差异是由于急切的加载。在生产中,所有文件都是急切加载的,因此运行控制台时所有常量都已存在。

当您在开发模式下运行控制台时,ActiveResource会尝试为该属性定义类名,但该机制不适用于您的用例。

如果the constant is not found on Objectit is created within the class that is being initializedValuation)。

为了使开发以与生产相同的方式工作,您需要绕过触发此自动加载机制。这可以使用Rails中的require_dependency方法轻松完成。

添加

require_dependency 'document'

class Valuation < ActiveResource::Base

Valuation课程之前,一切都应该正常工作。

此行确保在任何人尝试创建Document类的实例之前已加载Valuation常量,并且自动加载机制不会被使用。