ActiveRecord::HasManyThroughOrderError

9
我有一个关于3个模型之间的has_one关联,但出现了一个错误,提示“ActionView :: Template :: Error(在定义通过关联之前,不能有一个经由'Policy#invoice'的has_many:through关系'Policy#intermediary'。)”
保单模型
class Policy < ApplicationRecord

    self.table_name = "gipi_polbasic"
    self.primary_key = "policy_id"

    has_one :invoice
    has_one :intermediary, through: :invoice, foreign_key: :intrmdry_intm_no

中介模型
class Intermediary < ApplicationRecord
    self.table_name = "giis_intermediary"
    self.primary_key = "intm_no"

    has_one :invoice, foreign_key: :intrmdry_intm_no
    belongs_to :policy, foreign_key: :policy_id

发票模型
class Invoice < ApplicationRecord
    self.table_name = "gipi_comm_invoice"
    self.primary_key = "intrmdry_intm_no"

    belongs_to :policy, foreign_key: :policy_id
    belongs_to :intermediary, foreign_key: :intrmdry_intm_no

在政策中使用中介是否正确?我认为不是。如果中介属于发票而不是发票属于中介,那么就是正确的。 - Mahmoud Sayed
尝试过了,但仍然显示相同的错误。 - Cj Monteclaro
它在之前的Rails版本上运行正常,但在我更新到Rails 5.1.1后出现了错误。 - Cj Monteclaro
4个回答

16

2
我将我的belongs_to代码放在了has_many代码之上,这对我解决了问题。感谢提示! - Francis Malloch
还要检查一下是否定义了两次关系——在Rails 4.x中,这可能会被忽略,但在5.x中,它是一个错误(应该是这样的!) - Meekohi

4

以下是一种查找重复关联定义的技巧,适用于由多个猴子补丁组成的模型。

首先,找到has_many方法:

ActiveRecord::Associations::ClassMethods.instance_method(:has_many).source_location

然后,编辑那个文件:

    def has_many(name, scope = nil, options = {}, &extension)
      $has_manies ||= {}                               # <- Added
      $has_manies[[name, self]] ||= []                 # <- Added
      $has_manies[[name, self]] << [options,caller[0]] # <- Added
      reflection = Builder::HasMany.build(self, name, scope, options, &extension)
      Reflection.add_reflection self, name, reflection
    end

那么捕获 HasManyThroughOrderError 并启动调试器。执行以下代码:

$has_manies[[:intermediary, Policy]]

您不仅可以看到该关联是否定义了多次,还可以看到定义发生的位置。


1
请确保您的Policy模型中没有另一个多余的has_one :intermediary。更新后出现了相同的错误。

我没有一个,这不是Rails 5.1.1的一个bug吗?因为我的应用程序在Rails 5.0.3上运行正常。 - Cj Monteclaro
当我从5.0.3更新到5.1.1时,我遇到了完全相同的错误。实际上,在那个模型中我有很多关系,所以我一开始没有注意到 :) - Nick Pridorozhko

0

似乎新规则是必须先定义关系才能使用。

例如,在Rails 5.1中,以下代码将无法正常工作:

class User < ActiveRecord::Base
  has_many :phone_calls,
           :through => :phone_call_participants,
           :source => :phone_call
  has_many :phone_call_participants, :as => :participant
end

但是这个会:

class User < ActiveRecord::Base
  has_many :phone_call_participants, :as => :participant
  has_many :phone_calls,
           :through => :phone_call_participants,
           :source => :phone_call
end

我猜这会加速代码解释,因为文件不需要被扫描那么多次了?

1
你对代码解释理论的理解是错误的。这个错误是在扫描Hash的键时引发的,通过调用该Hashkeys方法获得。如果键不按预期顺序排列,则会引发错误。 - Throw Away Account
感谢您的反馈。 - Jared Menard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接