Rails4对某种类型的多态关系

时间:2015-11-11 00:25:24

标签: ruby-on-rails ruby-on-rails-4

我有多态关系:

class User < ActiveRecord::Base
  has_one :address
end

class Group < ActiveRecord::Base
  has_one :address
end

class Address < ActiveRecord::Base
  belongs_to :owner, polymorphic: true
end

如果存在,我想向has_one :user模型添加has_one :groupAddress关系。

使用Rails3,它有效:

class Address < ActiveRecord::Base
  belongs_to :user, conditions: ['owner_type = ?', 'User']
  belongs_to :group, conditions: ['owner_type = ?', 'Group']
end

但是现在条件在Rails4中消失了,我不知道如何处理这个问题。

我试过了:

class Address < ActiveRecord::Base
  belongs_to :user, -> {user_owner}, class_name: 'User', foreign_key: 'owner_id'
  scope :user_owner, where(owner_type: 'User')
end

但由于在User模型中搜索范围并且出现user.owner_type does not exist错误,因此无效。

最后,我希望能够编写例如:Address.joins(:user).where(whatever: true)

2 个答案:

答案 0 :(得分:2)

has_one不是正确的方法,因为地址belongs_to ownerhas_one期望foreign_key位于关联表中。

如果我理解正确,如果所有者为address.user,则您希望User返回用户实例,否则返回nil(与address.group相反)。如果是这种情况,您可以为此创建一个简单的方法:

class Address < ActiveRecord::Base
  belongs_to :owner, polymorphic: true

  def user
    owner_type == "User" ? self.owner : nil
  end

  def group
    owner_type == "Group" ? self.owner : nil
  end

  #these may create some confusion, but they will only be used with joins
  #maybe wrap them in their own Concern to have all the code in one 
  #location to make it clear for other team members

  #user_for_join will return the wrong association is address.owner_type != "User"
  belongs_to :user_for_join, foreign_key: :owner_id, class_name: User

  #group_for_join will return the wrong association is address.owner_type != "Group"
  belongs_to :group_for_join, foreign_key: :owner_id, class_name: Group

 def self.address_with_users
   #instead of calling Address.joins(:user), you now call Address.address_with_users
   self.where(owner_type: "User").joins(:user_for_join)
 end

 def self.address_with_groups
   self.where(owner_type: "Group").joins(:group_for_join)
 end


end

答案 1 :(得分:0)

Rails Test code有一个例子,他们使用lambda

belongs_to :user_with_conditions, -> { where :owner_type => 'User'}, :polymorphic => true,