我有一个复杂的情况,我正在开发一个Rails 3引擎,我只是间歇地得到标题中的错误。这是堆栈跟踪:
ActiveRecord::ConfigurationError - Association named 'whatever' was not found; perhaps you misspelled it?:
activerecord (3.2.18) lib/active_record/associations/preloader.rb:150:in `block in records_by_reflection'
activerecord (3.2.18) lib/active_record/associations/preloader.rb:146:in `records_by_reflection'
activerecord (3.2.18) lib/active_record/associations/preloader.rb:139:in `grouped_records'
activerecord (3.2.18) lib/active_record/associations/preloader.rb:130:in `preload_one'
activerecord (3.2.18) lib/active_record/associations/preloader.rb:109:in `preload'
activerecord (3.2.18) lib/active_record/associations/preloader.rb:98:in `block in run'
activerecord (3.2.18) lib/active_record/associations/preloader.rb:98:in `run'
activerecord (3.2.18) lib/active_record/relation.rb:181:in `block in exec_queries'
activerecord (3.2.18) lib/active_record/relation.rb:180:in `exec_queries'
activerecord (3.2.18) lib/active_record/relation.rb:160:in `block in to_a'
activerecord (3.2.18) lib/active_record/explain.rb:41:in `logging_query_plan'
activerecord (3.2.18) lib/active_record/relation.rb:159:in `to_a'
activerecord (3.2.18) lib/active_record/relation/delegation.rb:39:in `+'
/Users/me/src/appointment_engine/app/controllers/appointment_engine/appointments_controller.rb:42:in `block (3 levels) in index'
/Users/me/src/appointment_engine/app/controllers/appointment_engine/appointments_controller.rb:41:in `block (2 levels) in index'
actionpack (3.2.18) lib/action_controller/metal/mime_responds.rb:196:in `respond_to'
/Users/me/src/appointment_engine/app/controllers/appointment_engine/appointments_controller.rb:12:in `index'
总结:引擎中有一个名为Appointment
的模型,它与has_many :through
多态关联到主机应用的User
模型(这是一个要求,因为我们还关联到另一个模型)。以下是has_many
Appointment
声明
class Appointment < ActiveRecord::Base
has_many :scheduleables,
through: :appointments_scheduleables,
source_type: KAE.scheduleable_class.name
has_many :schedulers,
through: :appointments_schedulers,
source_type: KAE.scheduler_class.name
end
我遇到了第一个问题;我需要在:source_type
多态关联上设置has_many :through
(没有它就行不通),为此我需要知道关联模型的类,但是当我的引擎Appointment
时模型加载它是在主机应用程序的User
模型加载之前执行的,因此我的引擎模块KAE
尚未收到KAE.scheduleable_class
的值。
以下是KAE
收到该值的方式:
# in host app
class User < ActiveRecord::Base
acts_as_scheduler
end
我将acts_as_scheduler
写为AR mixin,它会将has_many :through
关联声明为Appointment
。
我的第一次尝试解决这个问题:我将Appointment
的{{1}}声明放在铁路内的钩子中:
has_many
好的,现在有效,我等到主机应用程序完全加载,现在我有ActiveSupport.on_load :after_initialize do
KAE::Appointment.class_eval do
has_many :scheduleables,
through: :appointments_scheduleables,
source_type: KAE.scheduleable_class.name
has_many :schedulers,
through: :appointments_schedulers,
source_type: KAE.scheduler_class.name
end
end
和KAE.scheduleable_class
的值,非常好。
除了我间歇性地收到标题中的错误!
我可以正常启动,使用该应用程序一段时间(10-30分钟),然后出于无处繁荣!我在KAE.scheduler_class
,rails server
和thin
下尝试过了。所有相同,所以它必须是一个应用程序/框架级错误。我查看活动记录预加载器类到堆栈跟踪顶部指向的位置:
unicorn
模型如何忘记它的某些关联?
所以现在我直接在# lib/active_record/associations/preloader.rb:150
def records_by_reflection(association)
records.group_by do |record|
reflection = record.class.reflections[association]
unless reflection
raise ActiveRecord::ConfigurationError, "Association named '#{association}' was not found; " \
"perhaps you misspelled it?"
end
reflection
end
end
模型中这样做,它似乎工作到目前为止,但它真的很难看:
Appointment
有人知道在Rails 3引擎中声明class Appointment < ActiveRecord::Base
if KAE.scheduler_class && KAE.scheduleable_class
has_many :scheduleables,
through: :appointments_scheduleables,
source_type: KAE.scheduleable_class.name
has_many :schedulers,
through: :appointments_schedulers,
source_type: KAE.scheduler_class.name
else
binding.pry # TODO
ActiveSupport.on_load :after_initialize do
KAE::Appointment.class_eval do
has_many :scheduleables,
through: :appointments_scheduleables,
source_type: KAE.scheduleable_class.name
has_many :schedulers,
through: :appointments_schedulers,
source_type: KAE.scheduler_class.name
end
end
end
end
多态关联的更好方法吗?
我一直在研究像has_many :through
和acts_as_taggable_on_steroids
这样的开源项目,看看他们是如何进行关联的,但他们没有多态paper_trail
。
有人知道有这种关联的项目吗?
答案 0 :(得分:0)
使用Rails自动加载+自动重新加载魔法加载排序可能很痛苦。在这些情况下,我只是让我的依赖更明确。我建议您尝试在主机中使用Rails的require_dependency
以确保不会发生这种情况:
# in host app
require_dependency 'appointment'
class User < ActiveRecord::Base
acts_as_scheduler
end
ActiveSupport的require
版本也适用于开发环境的自动重新加载,这可能是您在处理应用程序时间歇性地遇到此问题的原因。