【发布时间】:2014-05-29 18:17:40
【问题描述】:
我有一个复杂的案例,我正在开发 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 模型(这是一个要求,因为我们还关联到另一个模型)。这是Appointment 中的has_many 声明
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
在这里我遇到了我的第一个问题;我需要在has_many :through 多态关联上设置:source_type(没有它就无法工作),为此我需要知道关联模型的类,但是当我的引擎的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 的 has_many 声明放在 railtie 内的挂钩中:
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 和 KAE.scheduler_class 的值,太棒了。
除非我间歇性地收到标题中的错误!
我可以正常启动,使用该应用程序一段时间(10-30 分钟),然后突然轰隆隆!我在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 模型中执行此操作,到目前为止它似乎可以正常工作,但它真的很难看:
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
有人知道在 Rails 3 引擎中声明has_many :through 多态关联的更好方法吗?
我一直在研究像 acts_as_taggable_on_steroids 和 paper_trail 这样的开源项目,看看它们是如何进行关联的,但它们没有多态 has_many :through。
有人知道有这种关联的项目吗?
【问题讨论】:
标签: ruby-on-rails-3 activerecord polymorphic-associations rails-engines