通过关注建立两个模型之间的关系

时间:2021-03-15 14:04:59

标签: ruby-on-rails ruby database validation

我有模型 ProvinceUser,如果用户的地址中有该省,我需要阻止该省被删除。

由于模型 User.province 中包含以下问题,我可以做到 User

module MyAddressable
  extend ActiveSupport::Concern
  included do
    has_one     :address, as: :addressable, dependent: :destroy
    has_one     :city, through: :address
    has_one     :province, through: :city
    has_one     :zone, through: :city

    accepts_nested_attributes_for :address, reject_if: :reject_address, allow_destroy: true
  end
end

我正在尝试通过以下方式建立省和用户之间的关系,以便能够执行类似 Province.users 的操作:

has_many :users, through: :myaddresable

结果如下:

ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :myaddresable in model Province

如果我尝试将关系定义为

has_many :users, through: :addressable

能做到吗?如果是这样,正确的做法是什么?

1 个答案:

答案 0 :(得分:1)

has_many :users, through: :addressable 不起作用,因为 Province 模型不了解 Address 模型。

我们可以通过Province模型建立User模型和Address模型之间的关系。

以下设置适用于 rails 6

用户模型

class User < ApplicationRecord
  has_one     :address, as: :addressable, dependent: :destroy
  has_one     :city, through: :address
  has_one     :province, through: :city
end

省模式

class Province < ApplicationRecord
  has_many :cities

  has_many :users, through: :cities
end

城市模型

class City < ApplicationRecord
  has_many :addresses

  has_many :users,
           through: :addresses,
           source: :addressable,
           source_type: 'User'

  belongs_to :province
end

地址模型

class Address < ApplicationRecord
  belongs_to :addressable, polymorphic: true

  belongs_to :city
end

让我们假设根据模型关联正确定义了迁移。现在以下查询有效...

irb(main): > User.first.province

DEBUG -- :   User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
DEBUG -- :   Province Load (0.3ms)  SELECT "provinces".* FROM "provinces" INNER JOIN "cities" ON "provinces"."id" = "cities"."province_id" INNER JOIN "addresses" ON "cities"."id" = "addresses"."city_id" WHERE "addresses"."addressable_id" = $1 AND "addresses"."addressable_type" = $2 LIMIT $3  [["addressable_id", 1], ["addressable_type", "User"], ["LIMIT", 1]]

irb(main): > Province.first.users

DEBUG -- :   Province Load (0.5ms)  SELECT "provinces".* FROM "provinces" ORDER BY "provinces"."id" ASC LIMIT $1  [["LIMIT", 1]]
DEBUG -- :   User Load (0.5ms)  SELECT "users".* FROM "users" INNER JOIN "addresses" ON "users"."id" = "addresses"."addressable_id" INNER JOIN "cities" ON "addresses"."city_id" = "cities"."id" WHERE "cities"."province_id" = $1 AND "addresses"."addressable_type" = $2  [["province_id", 1], ["addressable_type", "User"]]

在您的情况下,由于 MyAddressable 问题已包含在 User 模型中,因此只需要定义其他关联和迁移。

希望这会有所帮助。谢谢。