【问题标题】:Establishing a relationship between two models through a Concern通过 Concern 建立两个模型之间的关系
【发布时间】:2021-03-15 14:04:59
【问题描述】:

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

由于模型User中包含以下关注点,我可以做到User.province

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 和 User 之间的关系,以便能够通过以下方式执行 Province.users 之类的操作:

has_many :users, through: :myaddresable

结果如下:

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

如果我尝试将关系定义为同样的事情

has_many :users, through: :addressable

这可以吗?如果是这样,正确的做法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby database validation


    【解决方案1】:

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

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

    以下设置适用于 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 模型中,因此只需要定义其他关联和迁移。

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

    【讨论】:

    • 成功了!惊人的!非常感谢!
    • 很高兴听到这个消息!解决这个问题很有趣。也谢谢你的问题。 :-)
    猜你喜欢
    • 2020-01-01
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 2017-09-18
    相关资源
    最近更新 更多