简体   繁体   English

autoload_paths不知道命名空间?

[英]autoload_paths not aware of namespace?

In app/services , I have some classes, as Notification::Finder and Notification::Builder . app/services ,我有一些类,如Notification::FinderNotification::Builder

They are placed as app/services/notification/builder.rb and app/services/notification/finder.rb . 它们被放置为app/services/notification/builder.rbapp/services/notification/finder.rb

There is also the Notification class as a model, at app/models/notification.rb app/models/notification.rb还有Notification类作为模型

The autoload_path is configurated as in config.autoload_paths += %W(#{config.root}/app/services) autoload_path的配置与config.autoload_paths += %W(#{config.root}/app/services)

When I try to load Finder , it works: 当我尝试加载Finder ,它可以工作:

Loading development environment (Rails 3.2.9)
[1] pry(main)> Notification::Finder
=> Notification::Finder

But when I try the Builder , I get a problem with the rails autoloading: 但是当我尝试使用Builder ,我遇到了rails自动加载的问题:

Loading development environment (Rails 3.2.9)
[1] pry(main)> Notification::Builder
=> ActiveRecord::Associations::Builder

It just ignores the namespace I've used when the constant name (Builder) has already been defined by other namespace, and gets the ActiveRecord::Associations::Builder instead. 它只是忽略了我在其他命名空间已经定义了常量名称(Builder)时使用的命名空间,而是获取了ActiveRecord::Associations::Builder

Is this the expected behavior, or a rails bug? 这是预期的行为还是铁轨错误?

Going more detailed, the const_missing method at activesupport/dependencies.rb receives a const_name 'Builder' , and nesting.inspect => 'nil' . 更详细一点, activesupport/dependencies.rbconst_missing方法接收const_name 'Builder' ,并且nesting.inspect => 'nil'

Curious that when I use constantize, it resolves as expected: 好奇当我使用constantize时,它按预期结算:

Loading development environment (Rails 3.2.9)
[1] pry(main)> 'Notification::Builder'.constantize
=> Notification::Builder

( Rails issue at github: https://github.com/rails/rails/issues/8726 ) (Rails在github上发布: https//github.com/rails/rails/issues/8726

ActiveRecord::Associations::Builder is a module in Rails. ActiveRecord :: Associations :: Builder是Rails中的一个模块。 If you have a Notification::Builder, you can ask it its class: 如果你有一个Notification :: Builder,你可以问它它的类:

>> Notification::Builder
=> ActiveRecord::Associations::Builder
>> Notification::Builder.class
=> Module
>> Notification::Builder.ancestors
=> [ActiveRecord::Associations::Builder]

Is this expected behavior? 这是预期的行为吗?

Yes

OK, so... what choices do you have? 好的,那么......你有什么选择?

  • You can use a different term than Builder. 您可以使用与Builder不同的术语。 Like Factory. 喜欢工厂。 or Notification::NotificationBuilder 或通知:: NotificationBuilder

More info: 更多信息:
* http://www.rubydoc.info/docs/rails/3.1.1/ActiveRecord/Associations/Builder/Association * http://www.rubydoc.info/docs/rails/3.1.1/ActiveRecord/Associations/Builder/Association
* http://apidock.com/rails/ActiveRecord/Associations/Builder * http://apidock.com/rails/ActiveRecord/Associations/Builder

This problem exists because you are using an ActiveRecord model as a namespace. 存在此问题是因为您使用ActiveRecord模型作为命名空间。 I created a gist with some experimentation until I saw the root cause. 我创造了一个带有一些实验的要点,直到我看到根本原因。

ActiveRecord models include the ActiveRecord::Associations module. ActiveRecord模型包括ActiveRecord::Associations模块。 Since you can get to a constant when including a module the Builder constant defined within Associations is now also reachable through the AR model. 由于在包含模块时可以获得常量,因此现在也可以通过AR模型访问在Associations定义的Builder常量。 You will get this behavior with every class defined in the modules, which are included into an AR model: 您将在模块中定义的每个类中获得此行为,这些类包含在AR模型中:

1.9.3-p194 :010 > Post.ancestors
 => [Post(id: integer, title: string, published_at: datetime, created_at: datetime, updated_at: datetime), Post::GeneratedFeatureMethods, #<Module:0x007fec74dc33a0>, ActiveRecord::Base, ActiveRecord::Core, ActiveRecord::Store, ActiveRecord::Serialization, ActiveModel::Serializers::Xml, ActiveModel::Serializers::JSON, ActiveModel::Serialization, ActiveRecord::Reflection, ActiveRecord::Transactions, ActiveRecord::Aggregations, ActiveRecord::NestedAttributes, ActiveRecord::AutosaveAssociation, ActiveModel::SecurePassword, ActiveRecord::Associations, ActiveRecord::Timestamp, ActiveModel::Validations::Callbacks, ActiveRecord::Callbacks, ActiveRecord::AttributeMethods::Serialization, ActiveRecord::AttributeMethods::Dirty, ActiveModel::Dirty, ActiveRecord::AttributeMethods::TimeZoneConversion, ActiveRecord::AttributeMethods::PrimaryKey, ActiveRecord::AttributeMethods::Query, ActiveRecord::AttributeMethods::BeforeTypeCast, ActiveRecord::AttributeMethods::Write, ActiveRecord::AttributeMethods::Read, ActiveRecord::AttributeMethods, ActiveModel::AttributeMethods, ActiveRecord::Locking::Pessimistic, ActiveRecord::Locking::Optimistic, ActiveRecord::CounterCache, ActiveRecord::Validations, ActiveModel::Validations::HelperMethods, ActiveSupport::Callbacks, ActiveModel::Validations, ActiveRecord::Integration, ActiveModel::Conversion, ActiveRecord::AttributeAssignment, ActiveModel::ForbiddenAttributesProtection, ActiveModel::DeprecatedMassAssignmentSecurity, ActiveRecord::Sanitization, ActiveRecord::Scoping::Named, ActiveRecord::Scoping::Default, ActiveRecord::Scoping, ActiveRecord::Inheritance, ActiveRecord::ModelSchema, ActiveRecord::ReadonlyAttributes, ActiveRecord::Persistence, Object, PP::ObjectMixin, ActiveSupport::Dependencies::Loadable, V8::Conversion::Object, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject] 

A possible solution is to use a module as a namespace. 一种可能的解决方案是使用模块作为命名空间。 For example module Notifications . 例如module Notifications

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM