在app/services
中,我有一些类,如Notification::Finder
和Notification::Builder
。
放置为app/services/notification/builder.rb
和app/services/notification/finder.rb
。
也有Notification
类作为模型,在app/models/notification.rb
autoload_path配置如config.autoload_paths += %W(#{config.root}/app/services)
当我尝试加载Finder
时,它工作:
Loading development environment (Rails 3.2.9)
[1] pry(main)> Notification::Finder
=> Notification::Finder
但是当我尝试Builder
时,我得到了rails自动加载的问题:
Loading development environment (Rails 3.2.9)
[1] pry(main)> Notification::Builder
=> ActiveRecord::Associations::Builder
当常量名称(Builder)已经被其他名称空间定义时,它只是忽略我使用的名称空间,并获得ActiveRecord::Associations::Builder
代替。
这是预期的行为,还是rails错误?
更详细地说,activesupport/dependencies.rb
的const_missing
方法接收const_name 'Builder'
和nesting.inspect => 'nil'
。
奇怪的是,当我使用constantise时,它会像预期的那样解析:
Loading development environment (Rails 3.2.9)
[1] pry(main)> 'Notification::Builder'.constantize
=> Notification::Builder
(Rails问题在github: https://github.com/rails/rails/issues/8726)
ActiveRecord::Associations::Builder是Rails中的一个模块。如果你有一个Notification::Builder,你可以问它的类:
>> Notification::Builder
=> ActiveRecord::Associations::Builder
>> Notification::Builder.class
=> Module
>> Notification::Builder.ancestors
=> [ActiveRecord::Associations::Builder]
这是预期行为吗?
是的
好的,所以…你有什么选择?
- 您可以使用与Builder不同的术语。像工厂。或通知::NotificationBuilder
更多信息:
* http://www.rubydoc.info/docs/rails/3.1.1/ActiveRecord/Associations/Builder/Association
* http://apidock.com/rails/ActiveRecord/Associations/Builder
这个问题存在是因为您使用ActiveRecord模型作为命名空间。我通过一些实验创造了一个要点,直到我发现了根本原因。
ActiveRecord
型号包括ActiveRecord::Associations
模块。由于您可以在包含模块时获得常量,因此在Associations
中定义的Builder
常量现在也可以通过AR模型访问。您将在模块中定义的每个类中获得这种行为,这些类包含在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]
一个可能的解决方案是使用模块作为命名空间。例如:module Notifications