Rails 4多个多态has_one关系不起作用

时间:2014-01-07 07:22:33

标签: ruby-on-rails ruby-on-rails-4 paperclip polymorphic-associations

我正在尝试从我的Booth模型中使用下面的

来获得三个多态关联
has_one :uploaded_file, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :uploaded_file

has_one :company_logo, as: :imageable, class_name: 'UploadedFile', dependent: :destroy
accepts_nested_attributes_for :company_logo

has_one :booth_main_image, as: :imageable, class_name: 'UploadedFile', dependent: :destroy
accepts_nested_attributes_for :booth_main_image

但这不起作用,当我在该协会的资源上单独使用build方法时,我在视图中获得相同的值。

在数据库的uploaded_files表中,我有imageable_idimageable_type 我希望将其重复用于公司徽标和展位主图像等内容,否则我必须创建更多列以支持其他多态关联,如果不使用它们将留下null

以下是UploadedFile的模型:

class UploadedFile < ActiveRecord::Base
    belongs_to :imageable, polymorphic: true

    has_attached_file :assets

    validates_attachment_content_type :assets, 
        :content_type => /^image\/(png|gif|jpeg)/,
        :default_url => "/images/:style/missing.png",
        :message => "only (png|gif|jpeg) images are allowed and the size cannot exceed 5mb",
        :size => { :in => 0..5000.kilobytes }

end

有没有办法为所有上述关联使用一组多态列?

1 个答案:

答案 0 :(得分:2)

您遇到此问题的原因是has_one将确保目标表中只有一条记录(在您的情况下为uploaded_files),将指向Booth模型。如果要区分同一模型的不同类型,则需要在某处设置一个标志,指示它是哪种类型。

要执行此操作,首先您需要添加标识图像类型的列:

# in a migration
def change
  add_column :uploaded_files, :image_type, :string
end

您可以将预期的图像类型定义为常量:

class UploadedFile < ActiveRecord::Base
  IMAGE_TYPE_STANDARD = 'Standard'
  IMAGE_TYPE_LOGO     = 'Logo'
  IMAGE_TYPE_BOOTH    = 'Booth'
end

现在你的协会应该反映这些类型:

class Booth < ActiveRecord::Base
  # optional - if you want to access all attached uploads
  has_many :uploaded_files, :as => :imageable, :dependent => :destroy

  has_one  :uploaded_file, :as => :imageable, :dependent => :destroy, 
           conditions: { image_type: UploadedFile::IMAGE_TYPE_STANDARD }
  has_one  :company_logo, :as => :imageable, :class_name => 'UploadedFile', 
           :dependent => :destroy, 
           conditions: { image_type: UploadedFile::IMAGE_TYPE_LOGO }
  has_one  :booth_main_image, :as => :imageable, :class_name => 'UploadedFile', 
           :dependent => :destroy, 
           conditions: { image_type: UploadedFile::IMAGE_TYPE_BOOTH }

  accepts_nested_attributes_for ...
end

请注意,您无需手动设置image_type。由于类型是由条件设置的,因此当您构建或创建其中一个has_one关联时,ActiveRecord将为您设置:

upload = @booth.build_uploaded_file(asset: some_asset)
upload.image_type 
=> 'Standard'