具有不同种类地址的配置文件和2个配置文件可以共享相同的地址

时间:2018-08-01 18:38:47

标签: ruby-on-rails associations

我有一个useLines表,其中有一个工作地址和一个家庭地址。如果这些个人资料的用户在一起住,则多个个人资料可以共享相同的家庭住址(如果他们一起工作,则可以共享工作地址)。我可以通过哪些方式实现这一目标?我认为flat在这种情况下会起作用,但是我想不出一种实现此方法的方法。

理想情况下,我希望能够执行类似Profilehas_many :through

的操作

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

方法1和2似乎不适用于我的情况,因为外键位于Profile.home_address表中,这将使一个地址仅绑定到一个Profile.addresses.where(address_type: "home")。方法3可行,但我只是想知道是否还有另一种方法可以做到。拥有AddressProfile似乎表明我拥有home_address_idwork_address_id模型。

2 个答案:

答案 0 :(得分:2)

首先,您可能希望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

注意:如果@profileaddress碰巧有多个address_type: 'home',则.first可能会也可能不会产生意外结果。

如果您有:

class User < ActiveRecord::Base
  has_one :profile

  delegate :home_address, to: :profile
end

然后您可以进行@user.home_address

答案 1 :(得分: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