【问题标题】:Rails 4 multiple polymorphic has_one relations not workingRails 4多个多态has_one关系不起作用
【发布时间】:2014-01-07 07:22:32
【问题描述】:

我正在尝试从我的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_id 和imageable_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

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

【问题讨论】:

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


    【解决方案1】:

    您遇到此问题的原因是因为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。由于类型是由条件设置的,ActiveRecord 会在您构建或创建 has_one 关联之一时为您设置它:

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

    【讨论】:

    • 在我看来,UploadedFile 类中的 CONSTANTS 类型表明需要更多类。为什么不为UploadedFile、CompanyLogo 和BoothMainImage 制作单独的模型?我认为这更容易推理。
    • 在更高版本的 Rails 4 中,条件键已被删除。我们现在应该怎么做?
    • @EtiennevanDelden conditions 替换为 where: has_one :uploaded_file, -&gt; { where image_type: UploadedFile::IMAGE_TYPE_STANDARD }, as: :imageable, dependent: :destroy
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    相关资源
    最近更新 更多