我的问题是基本相同的,因为这一个: 多态性协会与同一模型 <多个关联/ p>

然而,所提出/接受溶液不起作用,如由评论者稍后说明。

我有一个用遍了我的应用程序一类的照片。一个帖子可以有一个单一的照片。然而,我想重新使用多态的关系添加次级照片。

在:

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

class Post
   has_one :photo, :as => :attachable, :dependent => :destroy
end

所需:

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

然而,这种失败,因为它不能找到类“SecondaryPhoto”。根据我可以从其他线程知道的,我想做的事:

   has_one :secondary_photo, :as => :attachable, :class_name => "Photo", :dependent => :destroy

除了调用张贴#secondary_photo简单地返回通过照片关联,例如附接在相同的照片帖子#照片===帖子#secondary_photo。纵观SQL,它其中type =“照片”,而不是,比方说,“SecondaryPhoto”因为我想...

思考?谢谢!

有帮助吗?

解决方案

我已经做了,在我的项目。

诀窍是,照片需要将在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

此方法的好处是,当你创建使用@post.build_photo照片时,photo_type将自动预先填入相应的类型,比如“primary_photo”。 ActiveRecord的是足够聪明来做到这一点。

其他提示

4.2的Rails +

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

您需要提供根据foreign_key .... able'ness或Rails会要求在相片表POST_ID柱。 Attachable_type柱将与导轨魔术作为SecondaryPhoto填充

作为人检查此柱将来参考

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

的Rails 3:

has_one :banner_image, conditions: { attachable_type: 'ThemeBannerAttachment' }, class_name: 'Attachment', foreign_key: 'attachable_id', dependent: :destroy

导轨4:

has_one :banner_image, -> { where attachable_type: 'ThemeBannerAttachment'}, class_name: 'Attachment', dependent: :destroy

不知道为什么,但在Rails 3中,你需要旁边的条件和CLASS_NAME提供一个foreign_key值。不要使用“为:附”,因为这设置多态类型时,会自动使用调用类的名称。

上述适用于太的has_many

喜欢的东西下面的查询工作,但是从用户到地址分配不工作

用户类

has_many :addresses, as: :address_holder
has_many :delivery_addresses, -> { where :address_holder_type => "UserDelivery" },
       class_name: "Address", foreign_key: "address_holder_id"

地址类

belongs_to :address_holder, polymorphic: true

以前的答案都不帮我解决这个问题,所以我把这个在这里柜面别人运行到这一点。使用Rails 4.2 +。

创建迁移(假设你有一个地址表的话):

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

设置你的多态型的关联:

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

设置的类,其中所述关联将从被调用:

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

诀窍是,你必须调用关于Order实例构建方法或scope柱将不被填充。

所以这不起作用:

address = {attr1: "value"... etc...}
order = Order.new(bill_address: address)
order.save!

然而,这确实工作。

address = {attr1: "value"... etc...}
order = Order.new
order.build_bill_address(address)
order.save!

希望帮助别人。

我没有使用它,但我用Google搜索看去Rails的来源,我认为你要寻找的是:foreign_type。试试吧,告诉我们,如果它的工作原理:)

has_one :secondary_photo, :as => :attachable, :class_name => "Photo", :dependent => :destroy, :foreign_type => 'SecondaryPost'

我认为,输入您的问题应该是Post代替Photo和分别,这将是更好地使用SecondaryPost作为其分配到Post模型。

编辑:

以上的答案是完全地错了。 :foreign_type是在belongs_to关联availble的在多态模型来指定包含相关联的模型的类型的列的名称。

正如我看在滑轨来源,这条线将这种类型的关联:

dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as]

正如你可以看到它使用base_class.name获得类型名称。据我知道你可以做什么用的。

所以我sugestion是一列添加到照片模式,对例如:photo_type。并将其设置为0,如果它是第一张照片,或将其设置为1,如果它是第二张照片。在您的关联,添加:conditions => {:photo_type => 0}:conditions => {:photo_type => 1},分别。我知道这是不是你正在寻找一个解决方案,但我不能找到更好的东西。顺便说一句,也许这将是最好只使用has_many关联?

您将不得不猴补丁foreign_type的概念引入HAS_ONE关系。 这是我做了的has_many。在您初始化一个新的.rb文件夹我打电话给我的add_foreign_type_support.rb 它可以让您指定attachable_type是什么是。 例如:照片的has_many,:CLASS_NAME => “图片”,:如=>附接,:foreign_type => '产品图'

module ActiveRecord
  module Associations
    class HasManyAssociation < AssociationCollection #:nodoc:
      protected
        def construct_sql
          case
            when @reflection.options[:finder_sql]
              @finder_sql = interpolate_sql(@reflection.options[:finder_sql])
           when @reflection.options[:as]
              resource_type = @reflection.options[:foreign_type].to_s.camelize || @owner.class.base_class.name.to_s
              @finder_sql =  "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND "
              @finder_sql += "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(resource_type)}"
              else
                @finder_sql += ")"
              end
              @finder_sql << " AND (#{conditions})" if conditions

            else
              @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
              @finder_sql << " AND (#{conditions})" if conditions
          end

          if @reflection.options[:counter_sql]
            @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
          elsif @reflection.options[:finder_sql]
            # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
            @reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
            @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
          else
            @counter_sql = @finder_sql
          end
        end
    end
  end
end
# Add foreign_type to options list
module ActiveRecord
  module Associations # :nodoc:
     module ClassMethods
      private
        mattr_accessor :valid_keys_for_has_many_association
        @@valid_keys_for_has_many_association = [
          :class_name, :table_name, :foreign_key, :primary_key, 
          :dependent,
          :select, :conditions, :include, :order, :group, :having, :limit, :offset,
          :as, :foreign_type, :through, :source, :source_type,
          :uniq,
          :finder_sql, :counter_sql,
          :before_add, :after_add, :before_remove, :after_remove,
          :extend, :readonly,
          :validate, :inverse_of
        ]

    end
  end

对于 mongoid 使用此溶液

发现这个问题后,只好艰难的时刻,但有凉爽的解决方案,作品

添加到您的Gemfile

  

宝石 'mongoid-多个多态性'

并这个作品就像一个魅力:

  class Resource

  has_one :icon, as: :assetable, class_name: 'Asset', dependent: :destroy, autosave: true
  has_one :preview, as: :assetable, class_name: 'Asset', dependent: :destroy, autosave: true

  end

这些解决方案似乎都不on Rails的5工作出于某种原因,它看起来像周围的关联环境的行为发生了变化。在分配相关对象,似乎条件不插入使用;读取的关联只有当

我的解决办法来覆盖关联的setter方法:

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

def photo=(photo)
  photo.photo_type = 'primary_photo'
  super
end

您可以添加SecondaryPhoto模型,如:

class SecondaryPhoto < Photo
end
从HAS_ONE CLASS_NAME:

和然后跳过?secondary_photo

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top