ruby-on-rails – 使用STI的回形针的多个型号

目标:一个Rails模型(表),其中包含多个继承自它的模型,每个模型都定义了自己的回形针has_attached_file配置.

我以前有一个上传课程,我正在使用paperclip.问题是,当我添加更多文件类型(pdf,word文档等)时,它们仍然通过“style”和“convert_options”处理为图像.此外,现在我需要将一些文件存储在S3上,而其他文件存储在本地.

也就是说,我一直在重组一些东西,我现在有一个S3File,Contract和其他模型都继承自上传,它仍然继承自ActiveRecord :: Base.

# app/models/project.rb
class Project < ActiveRecord::Base
  has_many :contracts, :dependent => :destroy
    accepts_nested_attributes_for :contracts, :allow_destroy => true

  has_many :s3_files, :dependent => :destroy
    accepts_nested_attributes_for :s3_files, :allow_destroy => true
  # ...
end

# app/models/upload.rb
class Upload < ActiveRecord::Base
  belongs_to :project
end

# app/models/contract.rb
class Contract < Upload
  has_attached_file :item,
    :url  => "/projects/:project_id/uploads/:id/:basename.:extension",
    :path => ":rails_root/public/:class/:attachment/:id/:basename.:extension"

  do_not_validate_attachment_file_type :item
end

# app/models/s3_file.rb
class S3File < Upload
  has_attached_file :s3file,
    storage: :s3,
    url: ':s3_domain_url',
    path: lambda {|u| 'files/:basename.:extension' }

  do_not_validate_attachment_file_type :s3file
end

现在在我尝试查询数据的控制台中,它返回上传对象而不是S3File或Contract.

irb(main):005:0> Project.first.contracts
=> #<Upload id: 14833, project_id: 9717, upload_type: "private", item_file_name: "abcd.pdf", item_category: "contracts", item_content_type: "application/pdf", item_file_size: 671367, rake_processed: 0, name: "", created_at: "2013-05-30 20:05:02", updated_at: "2013-05-30 20:05:02">

将响应作为上载类型是有问题的,因为它没有回形针附件.这些是在子类上定义的,每个子类都具有has_attached_file的唯一URL,路径和存储定义.

我看到了multiple models and paperclippolymorphic multiple models paperclip问题,但在那些问题中,每个“多个模型”都继承自ActiveRecord :: Base,我的目标是避免这种情况,因为我可以,因为数据结构是相同的.

我对此的疑问是:

>这是使用具有一个表的各种存储后端的文件类型的正确方法吗?作为文件,它们大多数都具有相同的属性,因此对于每个模型都有多个表似乎是不必要的.
>我需要使用多态关联吗?我如何定义这些?我无法让它工作,加上它似乎不合适,因为合同和S3File无论如何都是上传类型,他们没有自己的表.
>使用单独的has_attached_file(:item或:s3file)名称是一个好主意还是让它们保持不变是有益的?

最佳答案 带回形针的STI已在几个问题
#293,
#601,
#605中讨论过,现在是回形针的支持功能.

STI是正确的方法吗?

在我的情况下,这是正确的方法,因为我不想为每个模型使用多个表.为了解决在查询project.contracts和获取上传类型类时出现错误类的问题,这是一个记录在案的Rails功能.只需添加class_name:“契约到您模型上的has_many将解决此问题:

associations documentation on customizing the query

Customizing the query

Associations are built from Relations, and you can use the Relation
syntax to customize them. For example, to add a condition:

 class Blog < ActiveRecord::Base   
     has_many :published_posts, -> { where published: true }, class_name: 'Post' 
 end 

多态关联是否必要

在这种情况下与STI,没有.如果每个模型都支持db,那么多态关联可能有所帮助.有关示例,请参阅polymorphic associations with multiple models的答案.

使用相同的has_attached_file是个好主意

自上述拉动请求合并以来,这在回形针中不是问题.可以覆盖子类中的选项,回调,样式,url或路径,并享受OOP的优势以满足应用程序的需要.

点赞