使用STI的回形针的多个模型

时间:2016-03-15 21:34:59

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

目标:一个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)名称是个好主意还是让它们保持不变是有益的?

1 个答案:

答案 0 :(得分:2)

带有回形针的STI已经在几个问题#293#601#605中进行了讨论,现在是回形针的支持功能。

STI是正确的方法吗?

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

根据associations documentation on customizing the query

  

自定义查询

     

关联是从Relations建立的,您可以使用Relation   语法来自定义它们。例如,要添加条件:

 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的优势以满足应用程序的需求。