【问题标题】:ActiveRecord::ConfigurationError - Association named 'whatever' was not foundActiveRecord::ConfigurationError - 未找到名为“whatever”的关联
【发布时间】: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

我第一次尝试解决这个问题:我将 Appointmenthas_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_classKAE.scheduler_class 的值,太棒了。

除非我间歇性地收到标题中的错误!

我可以正常启动,使用该应用程序一段时间(10-30 分钟),然后突然轰隆隆!我在rails serverthinunicorn下试过了;都一样,所以它必须是应用程序/框架级别的错误。我在活动记录预加载器类中查看堆栈跟踪顶部指向的位置:

# 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_steroidspaper_trail 这样的开源项目,看看它们是如何进行关联的,但它们没有多态 has_many :through

有人知道有这种关联的项目吗?

【问题讨论】:

    标签: ruby-on-rails-3 activerecord polymorphic-associations rails-engines


    【解决方案1】:

    使用 Rails 自动加载+自动重新加载魔法,加载排序可能会很痛苦。在这些情况下,我只是让我的依赖关系更加明确。我建议您尝试在主机中使用 Rails 的 require_dependency 以确保不会发生这种情况:

    # in host app
    require_dependency 'appointment'
    class User < ActiveRecord::Base
      acts_as_scheduler
    end
    

    ActiveSupport 的 require 版本也可以很好地配合开发环境的自动重新加载,这可能是您在处理应用程序时间歇性遇到此问题的原因。

    【讨论】:

    • 我没有想到。我会试一试。谢谢你的建议:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多