Rails多态关联在同一模型上具有多个关联

Mat*_*ish 55 ruby-on-rails polymorphic-associations

我的问题与此问题基本相同: 在同一模型上具有多个关联的多态关联

但是,提议/接受的解决方案不起作用,如后面的评论者所示.

我有一个Photo类,在我的应用程序中使用.帖子可以有一张照片.但是,我想重新使用多态关系来添加辅助照片.

之前:

class Photo 
   belongs_to :attachable, :polymorphic => true
end

class Post
   has_one :photo, :as => :attachable, :dependent => :destroy
end
Run Code Online (Sandbox Code Playgroud)

期望:

class Photo 
   belongs_to :attachable, :polymorphic => true
end

class Post
   has_one :photo,           :as => :attachable, :dependent => :destroy
   has_one :secondary_photo, :as => :attachable, :dependent => :destroy
end
Run Code Online (Sandbox Code Playgroud)

但是,由于无法找到"SecondaryPhoto"类,因此失败.基于我从其他线程可以看出的内容,我想做:

   has_one :secondary_photo, :as => :attachable, :class_name => "Photo", :dependent => :destroy
Run Code Online (Sandbox Code Playgroud)

除了调用Post#secondary_photo之外,只返回通过Photo Association附加的相同照片,例如Post#photo === Post#secondary_photo.看看SQL,它确实WHERE type ="Photo"而不是像我想要的那样"SecondaryPhoto"......

思考?谢谢!

Max*_*yak 71

我在我的项目中做到了这一点.

诀窍是照片需要一个将在has_one条件下使用的列来区分主要和次要照片.注意:conditions这里发生的事情.

has_one :photo, :as => 'attachable', 
        :conditions => {:photo_type => 'primary_photo'}, :dependent => :destroy

has_one :secondary_photo, :class_name => 'Photo', :as => 'attachable',
        :conditions => {:photo_type => 'secondary_photo'}, :dependent => :destroy
Run Code Online (Sandbox Code Playgroud)

这种方法@post.build_photo的优点在于,当您使用时创建照片时,photo_type将自动预先填充相应的类型,如"primary_photo".ActiveRecord非常聪明,可以做到这一点.

  • 有没有办法做同样的事情,因为在Rails 4中不推荐使用`conditions`? (10认同)
  • 上面的代码对我不起作用.:conditions => {:photo_type =>'primary_photo'}未更改photo_type列内容.它仍然是我的模型的类.做了什么工作是为数据库添加一个新列,photo_sub_type(字符串),并设置my:conditions => {:photo_sub_type =>'primary_photo'}但是每个关联都必须有:conditions => {:photo_sub_type => [指定值]}指定.但它的工作正如我所希望的那样.使用相同的照片模型将许多不同类型的照片附加到另一个模型. (6认同)
  • 对于任何挣扎于此解决方案的人:确保在`Photo`模型中设置`attr_accessible:photo_type`,否则你的`Post`模型将无法使用`:conditions`自动填充它.让我在那里停留了将近一个小时. (4认同)

小智 21

Rails 4.2+

class Photo
   belongs_to :attachable, :polymorphic => true
end

class Post
   has_one :photo, :as => :attachable, :dependent => :destroy
   has_one :secondary_photo, -> { where attachable_type: "SecondaryPhoto"},
     class_name: Photo, foreign_key: :attachable_id,
     foreign_type: :attachable_type, dependent: :destroy
end
Run Code Online (Sandbox Code Playgroud)

你需要根据......才能提供foreign_key,否则Rails会在照片表中询问post_id列.Attachable_type列将填充Rails魔法SecondaryPhoto


PR *_*ead 6

先前的答案都无法帮助我解决此问题,因此,如果有人遇到此问题,我将其放在此处。使用Rails 4.2 +。

创建迁移(假设您已经有一个Addresses表):

class AddPolymorphicColumnsToAddress < ActiveRecord::Migration
  def change
    add_column :addresses, :addressable_type, :string, index: true
    add_column :addresses, :addressable_id, :integer, index: true
    add_column :addresses, :addressable_scope, :string, index: true
  end
end
Run Code Online (Sandbox Code Playgroud)

设置您的多态关联:

class Address < ActiveRecord::Base
  belongs_to :addressable, polymorphic: true
end
Run Code Online (Sandbox Code Playgroud)

设置将在其中调用关联的类:

class Order < ActiveRecord::Base
  has_one :bill_address, -> { where(addressable_scope: :bill_address) }, as: :addressable,  class_name: "Address", dependent: :destroy
  accepts_nested_attributes_for :bill_address, allow_destroy: true

  has_one :ship_address, -> { where(addressable_scope: :ship_address) }, as: :addressable, class_name: "Address", dependent: :destroy
  accepts_nested_attributes_for :ship_address, allow_destroy: true
end
Run Code Online (Sandbox Code Playgroud)

诀窍是您必须在Order实例上调用build方法,否则scope将不会填充该列。

因此,这不起作用:

address = {attr1: "value"... etc...}
order = Order.new(bill_address: address)
order.save!
Run Code Online (Sandbox Code Playgroud)

但是,这确实可行。

address = {attr1: "value"... etc...}
order = Order.new
order.build_bill_address(address)
order.save!
Run Code Online (Sandbox Code Playgroud)

希望对别人有帮助。


Jel*_*Boy 5

检查这篇文章的人的未来参考

这可以使用以下代码实现......

Rails 3:

has_one :banner_image, conditions: { attachable_type: 'ThemeBannerAttachment' }, class_name: 'Attachment', foreign_key: 'attachable_id', dependent: :destroy
Run Code Online (Sandbox Code Playgroud)

导轨4:

has_one :banner_image, -> { where attachable_type: 'ThemeBannerAttachment'}, class_name: 'Attachment', dependent: :destroy
Run Code Online (Sandbox Code Playgroud)

不确定原因,但在Rails 3中,您需要在条件和class_name之外提供foreign_key值.不要使用'as :: attachachable',因为这会在设置多态类型时自动使用调用类名.

以上也适用于has_many.


san*_*ung 5

像下面这样的东西用于查询,但是从用户到地址的分配不起作用

用户类

has_many :addresses, as: :address_holder
has_many :delivery_addresses, -> { where :address_holder_type => "UserDelivery" },
       class_name: "Address", foreign_key: "address_holder_id"
Run Code Online (Sandbox Code Playgroud)

地址类

belongs_to :address_holder, polymorphic: true
Run Code Online (Sandbox Code Playgroud)