【问题标题】:How can I implement a has_many :through association two ways?如何实现 has_many :through 关联两种方式?
【发布时间】:2018-08-21 00:36:54
【问题描述】:

我有一个属性模型和一个用户模型。

具有“admin”角色的用户(由 users 表中的一列表示)可以具有许多属性。

具有“guest”角色的用户也可以属于某个属性,这使他们可以访问该属性。

我应该如何在 Rails 中做到这一点?

【问题讨论】:

    标签: ruby-on-rails activerecord associations


    【解决方案1】:

    授权表 -> user_id, property_id

    class Authorization < ActiveRecord::Base
        belongs_to :user
        belongs_to :property
    end 
    
    class User < ActiveRecord::Base
        has_many :authorizations
        has_many :properties, through: :authorizations
    end
    
    class Property < ActiveRecord::Base
        has_many :authorizations
        has_many :users, through: :authorizations
    end
    

    那你就可以User.find(id).properties

    【讨论】:

      【解决方案2】:

      首先,您的模型UserProperty 之间需要has_many :through 关联。因此,创建一个新表 properties_users,其中包含列 user_idpropety_id。并对模型进行以下更改:

      class PropertiesUser < ActiveRecord::Base
        belongs_to :user
        belongs_to :property
      end 
      
      class User < ActiveRecord::Base
        has_many :properties_users
        has_many :properties, through: :properties_users
      end
      
      class Property < ActiveRecord::Base
        has_many :properties_users
        has_many :users, through: :properties_users
      end
      

      现在,我们需要确保来宾用户没有多个属性。为此,我们可以向模型 PropertiesUser 添加验证,如下所示:

      class PropertiesUser < ActiveRecord::Base
        validate :validate_property_count_for_guest
      
        private
      
        def validate_property_count_for_guest
          return unless user && user.guest?
      
          if user.properties.not(id: self.id).count >= 1
            self.errors.add(:base, 'guest user cannot have more than one properties')
          end
        end
      end 
      
      class User < ActiveRecord::Base
        def guest?
          # return `true` if user is guest
        end
      end
      

      最后,要访问访客用户的属性,在模型User 中定义一个专用方法:

      class User < ActiveRecord::Base
        def property
          # Raise error if `property` is called on non-guest users
          raise 'user has multiple properties' unless guest?
      
          properties.first
        end
      end
      

      现在,您可以通过运行获取来宾用户的属性:

      user = User.first
      
      user.guest?
       => true
      
      user.property
       => <#Property 1>    # A record of Property
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-17
        相关资源
        最近更新 更多