ActiveResource 在开发中 运行 rails 控制台添加额外的 class
ActiveResource adds an extra class when running rails console in development
我们有 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>
所以文档的 class 名称是 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>
文档的 class 只是 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.
究竟是什么原因造成的?我已经检查了配置是否有任何切换 on/off 取决于环境,但我找不到任何东西。
ActiveResource 似乎正在使用 autoloading mechanism 将属性名称动态转换为 classes 以供集合使用。
因此,开发和生产之间的差异是由于预先加载。在生产中,所有文件都是预先加载的,因此当您 运行 控制台时,所有常量都已经存在。
当您在开发模式下 运行 设置控制台时,ActiveResource 会尝试为属性定义 class 名称,但该机制不适用于您的用例。
如果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
class 之前,一切都应该正常。
此行确保在任何人尝试创建 Valuation
class 的实例之前已经加载了 Document
常量,并且不会使用自动加载机制。
我们有 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>
所以文档的 class 名称是 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>
文档的 class 只是 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.
究竟是什么原因造成的?我已经检查了配置是否有任何切换 on/off 取决于环境,但我找不到任何东西。
ActiveResource 似乎正在使用 autoloading mechanism 将属性名称动态转换为 classes 以供集合使用。
因此,开发和生产之间的差异是由于预先加载。在生产中,所有文件都是预先加载的,因此当您 运行 控制台时,所有常量都已经存在。
当您在开发模式下 运行 设置控制台时,ActiveResource 会尝试为属性定义 class 名称,但该机制不适用于您的用例。
如果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
class 之前,一切都应该正常。
此行确保在任何人尝试创建 Valuation
class 的实例之前已经加载了 Document
常量,并且不会使用自动加载机制。