导入记录时 rails 中的反向有效性错误
Inverse validity error in rails when importing records
我在使用 sidekiq 导入记录时遇到错误 ActiveRecord::InverseOfAssociationNotFoundError (Could not find the inverse association for sponsorships (:sponsor_type in LegiscanModel::Sponsorship)
。以下是我的模型。
sponsorship.rb
class LegiscanModel::Sponsorship < ApplicationRecord
belongs_to :bill, class_name: 'LegiscanModel::Bill', foreign_key: 'bill_id', inverse_of: :sponsorships
belongs_to :sponsor, class_name: 'LegiscanModel::Politician', foreign_key: :politician_id, inverse_of: :sponsorships
accepts_nested_attributes_for :sponsor
delegate :full_name, to: :sponsor, prefix: true, allow_nil: true
validates :politician_id, uniqueness: { scope: :bill }
belongs_to :sponsorship_type, class_name: 'LegiscanModel::SponsorType', foreign_key: :sponsor_type_id, inverse_of: :sponsorships
end
sponsor_type.rb
class LegiscanModel::SponsorType < ApplicationRecord
has_many :sponsorships, class_name: 'LegiscanModel::Sponsorship', inverse_of: :sponsor_type, dependent: :destroy
end
politician.rb
has_many :sponsorships, dependent: :destroy, inverse_of: :sponsor, class_name: 'LegiscanModel::Sponsorship'
sidekiq 作业(部分)
def handle_sponsors(sponsors, bill_id)
sponsors.each do |sponsor|
LegiscanModel::Politician.find_by(people_id: sponsor['people_id']).tap do |politician|
LegiscanModel::Sponsorship.find_or_create_by!(politician_id: politician.id, bill_id: bill_id, sponsor_order: sponsor['sponsor_order'], sponsor_type_id: sponsor['sponsor_type_id'])
end
end
end
如果您实际上通过显式嵌套正确设置了 类 而不是使用范围解析运算符,则可以显着改进此代码:
module LegiscanModel
class Sponsorship < ApplicationRecord
belongs_to :bill
belongs_to :sponsor,
class_name: 'Politician', # specifying the module is optional
inverse_of: :sponsorships
belongs_to :sponsorship_type
accepts_nested_attributes_for :sponsor
delegate :full_name, to: :sponsor, prefix: true, allow_nil: true
# should be the database column since its used to create a query
validates :politician_id, uniqueness: { scope: :bill_id }
end
end
module LegiscanModel
class SponsorshipType < ApplicationRecord
has_many :sponsorships, dependent: :destroy
end
end
虽然这看起来像是一个微不足道的风格选择,但实际上并非如此 - 通过使用 module LegiscanModel
您将重新打开模块并设置模块嵌套,以便您可以引用同一命名空间中的常量。
这也避免了由于不断查找而导致的自动加载错误和错误。 ::
只应在引用常量时使用 - 而不是在定义常量时使用。
当可以从关联名称派生时,您也不需要指定外键选项。虽然它没有任何危害,但它会产生额外的噪音。 Rails 也可以自动推断逆。如果你想通过关联反射,你可以检查它:
LegiscanModel::Sponsorship.reflect_on_assocation(:sponsorship_type)
.inverse
我在使用 sidekiq 导入记录时遇到错误 ActiveRecord::InverseOfAssociationNotFoundError (Could not find the inverse association for sponsorships (:sponsor_type in LegiscanModel::Sponsorship)
。以下是我的模型。
sponsorship.rb
class LegiscanModel::Sponsorship < ApplicationRecord
belongs_to :bill, class_name: 'LegiscanModel::Bill', foreign_key: 'bill_id', inverse_of: :sponsorships
belongs_to :sponsor, class_name: 'LegiscanModel::Politician', foreign_key: :politician_id, inverse_of: :sponsorships
accepts_nested_attributes_for :sponsor
delegate :full_name, to: :sponsor, prefix: true, allow_nil: true
validates :politician_id, uniqueness: { scope: :bill }
belongs_to :sponsorship_type, class_name: 'LegiscanModel::SponsorType', foreign_key: :sponsor_type_id, inverse_of: :sponsorships
end
sponsor_type.rb
class LegiscanModel::SponsorType < ApplicationRecord
has_many :sponsorships, class_name: 'LegiscanModel::Sponsorship', inverse_of: :sponsor_type, dependent: :destroy
end
politician.rb
has_many :sponsorships, dependent: :destroy, inverse_of: :sponsor, class_name: 'LegiscanModel::Sponsorship'
sidekiq 作业(部分)
def handle_sponsors(sponsors, bill_id)
sponsors.each do |sponsor|
LegiscanModel::Politician.find_by(people_id: sponsor['people_id']).tap do |politician|
LegiscanModel::Sponsorship.find_or_create_by!(politician_id: politician.id, bill_id: bill_id, sponsor_order: sponsor['sponsor_order'], sponsor_type_id: sponsor['sponsor_type_id'])
end
end
end
如果您实际上通过显式嵌套正确设置了 类 而不是使用范围解析运算符,则可以显着改进此代码:
module LegiscanModel
class Sponsorship < ApplicationRecord
belongs_to :bill
belongs_to :sponsor,
class_name: 'Politician', # specifying the module is optional
inverse_of: :sponsorships
belongs_to :sponsorship_type
accepts_nested_attributes_for :sponsor
delegate :full_name, to: :sponsor, prefix: true, allow_nil: true
# should be the database column since its used to create a query
validates :politician_id, uniqueness: { scope: :bill_id }
end
end
module LegiscanModel
class SponsorshipType < ApplicationRecord
has_many :sponsorships, dependent: :destroy
end
end
虽然这看起来像是一个微不足道的风格选择,但实际上并非如此 - 通过使用 module LegiscanModel
您将重新打开模块并设置模块嵌套,以便您可以引用同一命名空间中的常量。
这也避免了由于不断查找而导致的自动加载错误和错误。 ::
只应在引用常量时使用 - 而不是在定义常量时使用。
当可以从关联名称派生时,您也不需要指定外键选项。虽然它没有任何危害,但它会产生额外的噪音。 Rails 也可以自动推断逆。如果你想通过关联反射,你可以检查它:
LegiscanModel::Sponsorship.reflect_on_assocation(:sponsorship_type)
.inverse