5

In app/services habe ich einige Klassen, wie Notification::Finder und Notification::Builder.autoload_paths nicht bekannt, Namespace?

Sie werden als app/services/notification/builder.rb und app/services/notification/finder.rb platziert.

Es gibt auch die Notification Klasse als Modell, bei app/models/notification.rb

Die autoload_path wie in config.autoload_paths += %W(#{config.root}/app/services)

konfiguriert ist, wenn ich versuche, Finder zu laden, funktioniert es:

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

Aber wenn Ich versuche die Builder, bekomme ich ein Problem mit den Schienen Autoloading:

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

Es ignoriert nur den Namespace, den ich verwendet habe, wenn der konstante Name (Builder) bereits von einem anderen Namespace definiert wurde, und erhält stattdessen die ActiveRecord::Associations::Builder.

Ist dies das erwartete Verhalten oder ein Rails Bug?

gehen detaillierter, die const_missing Verfahren bei activesupport/dependencies.rb empfängt ein const_name 'Builder' und nesting.inspect => 'nil'.

Neugierig, dass, wenn ich constantize verwenden, ist es wie erwartet aufgelöst:

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

(Rails Problem bei Github: https://github.com/rails/rails/issues/8726)

+1

Ist es möglich, dass 'Builder' ein reservierter Name ist? – tadman

+2

@tadman es ist nicht =/ –

+1

können Sie es in einer neuen Anwendung reproduzieren? Wenn ja, bitte gib mir Github und lass es mich wissen. Ich werde es mir ansehen. Es gibt Situationen, in denen der Rails-Autoloader das richtige Ergebnis nicht zurückgeben kann. Ich denke, das sollte möglich sein, aber ... –

Antwort

2

Active :: Verbände :: Builder ist ein Modul in Rails. Wenn Sie eine Benachrichtigung haben :: Builder, können Sie es seine Klasse fragen:

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

das erwartete Verhalten ist?

Ja

OK, so ... Welche Möglichkeiten haben Sie?

  • können Sie einen anderen Begriff als Builder verwenden. Wie Fabrik. oder Mitteilung :: NotificationBuilder

Weitere Informationen:
* http://www.rubydoc.info/docs/rails/3.1.1/ActiveRecord/Associations/Builder/Association
* http://apidock.com/rails/ActiveRecord/Associations/Builder

1

Dieses Problem besteht, weil Sie ein Activerecord-Modell als Namespace verwenden. Ich habe mit einigen Experimenten einen Grundstein gelegt, bis ich die Ursache sah.

Modelle enthalten das ActiveRecord::Associations Modul.Da Sie beim Einbinden eines Moduls eine Konstante erreichen können, ist die Builder Konstante, die in Associations definiert ist, nun auch über das AR-Modell erreichbar. Sie dieses Verhalten mit jeder Klasse erhalten in den Modulen definiert, die in ein AR-Modell enthalten sind:

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] 

Eine mögliche Lösung ist ein Modul als Namespace zu verwenden. Zum Beispiel module Notifications.

Verwandte Themen