【问题标题】:Profile having Address of different kinds and 2 profiles may share the same address具有不同类型地址的配置文件和 2 个配置文件可能共享相同的地址
【发布时间】:2018-08-01 18:38:47
【问题描述】:

我有一个Profile 表,其中包含一个工作地址和一个家庭地址。如果这些个人资料的用户住在一起,则多个个人资料可以共享相同的家庭地址(如果他们一起工作,则可以共享工作地址)。有什么方法可以实现这一目标?我认为has_many :through 在这种情况下会起作用,但我想不出一种方法来实现它。

理想情况下,我希望能够执行Profile.home_addressProfile.addresses.where(address_type: "home") 之类的操作

我在寻找一些答案时看到了这个帖子: Order having multiple addresses of different kinds

方法 1 和 2 似乎不适用于我的情况,因为外键位于 Address 表中,这将允许地址仅绑定到一个 Profile。方法 3 会起作用,但我只是想知道是否有另一种方法可以做到这一点。拥有home_address_idwork_address_id 似乎表明我拥有HomeAddressWorkAddress 模型。

【问题讨论】:

    标签: ruby-on-rails associations


    【解决方案1】:

    首先,您可能希望ProfileAddress 具有m:m 关系。这可能看起来像:

    class Profile < ActiveRecord::Base
      has_many    :profile_addresses
      has_many    :addresses, through: :profile_addresses
      belongs_to  :user
    end
    
    class Address < ActiveRecord::Base
      has_many :profile_addresses
      has_many :profiles, through: :profile_addresses
    end
    
    class ProfileAddress < ActiveRecord::Base
      belongs_to :profile
      belongs_to :address
    end
    

    现在,您可以使用@profile.addresses。如果你想能够做到@profile.home_address(不是Profile.home_address,因为你想在一个实例上调用方法,而不是一个类),那么你可以这样做:

    class Profile < ActiveRecord::Base
      has_many    :profile_addresses
      has_many    :addresses, through: :profile_addresses
      belongs_to  :user
    
      def home_address
        addresses.where(address_type: 'home').first
      end
    
    end
    

    注意:如果@profile 恰好有多个addressaddress_type: 'home',那么.first 可能会也可能不会产生意外结果。

    如果你有:

    class User < ActiveRecord::Base
      has_one :profile
    
      delegate :home_address, to: :profile
    end
    

    那你就可以@user.home_address了。

    【讨论】:

      【解决方案2】:

      假设以下场景:

      • 个人资料可以有多个地址,但每种类型只能一个,即“家”、“工作”等。
      • 一个地址可以关联到多个个人资料,以防人们住在同一个房子或在同一个办公室工作。
      • 一个地址可以是一个个人资料(用户)的“家庭”地址,同一个地址可以是另一个个人资料(用户)的“工作”地址(可能,不是吗?) .

      我最终得到了一种简单的方法,如下所示:

      class Profile
        has_many :profile_addresses
      
        def home_address
          profile_addresses.where(tag: 'home').first&.address
        end
      
        def work_address
          profile_addresses.where(tag: 'work').first&.address
        end
      end
      
      class ProfileAddress
        # field :tag
      
        belongs_to :profile
        belongs_to :address
      end
      
      class Address      
      end
      

      现在让我们创建和访问一些记录:

      profile_1 = Profile.find(1)
      
      address_1 = Address.create(
        street: '22-Block',
        region: 'Connaught Place',
        city: 'New Delhi',
        state: 'Delhi',
        country: 'IN'
      )
      
      # Say, `profile_1` has above `address_1` as its home address
      profile_1.profile_addresses.create(tag: 'home', address: address_1)
      
      address_2 = Address.create(
        street: 'Street-43',
        region: 'Raja Garden',
        city: 'Mohali',
        state: 'Punjab',
        country: 'IN'
      )
      
      # `profile_1` has above `address_2` as its work address
      profile_1.profile_addresses.create(tag: 'work', address: address_2)
      
      # Another profile
      profile_2 = Profile.find(2)
      
      # Now, say, `profile_2` has `address_1` as its work address
      profile_2.profile_addresses.create(tag: 'work', address: address_1)
      
      # Fetching...
      profile_1.home_address
       => address_1
      
      profile_1.work_address
       => address_2
      
      profile_2.home_address
       => nil
      
      profile_2.work_address
       => address_1
      

      【讨论】:

        猜你喜欢
        • 2019-11-06
        • 1970-01-01
        • 1970-01-01
        • 2015-06-16
        • 1970-01-01
        • 1970-01-01
        • 2022-01-21
        • 1970-01-01
        • 2010-12-14
        相关资源
        最近更新 更多