我有一个rails应用程序,它有多个带有回形针附件的模型,这些附件都上传到S3.这个应用程序还有一个经常运行的大型测试套件.这样做的缺点是,每次测试运行时都会有大量文件上传到我们的S3帐户,这使得测试套件运行缓慢.这也会降低开发速度,并且需要您有一个互联网连接才能处理代码.

有没有一种合理的方法可以根据Rails环境设置回形针存储机制?理想情况下,我们的测试和开发环境将使用本地文件系统存储,而生产环境将使用S3存储.

我还想将这种逻辑提取到某种共享模块中,因为我们有几个模型需要这种行为.我希望在每个模型中都避免这样的解决方案:

### We don't want to do this in our models...
if Rails.env.production?
  has_attached_file :image, :styles => {...},
                    :path => "images/:uuid_partition/:uuid/:style.:extension",
                    :storage => :s3,
                    :url => ':s3_authenticated_url', # generates an expiring url
                    :s3_credentials => File.join(Rails.root, 'config', 's3.yml'),
                    :s3_permissions => 'private',
                    :s3_protocol => 'https'
else
  has_attached_file :image, :styles => {...},
                    :storage => :filesystem
                    # Default :path and :url should be used for dev/test envs.
end

Update:最棘手的是,附件的:path:url选项需要根据使用的存储系统而有所不同.

任何建议都将不胜感激!:-)

推荐答案

在玩了一段时间后,我想出了一个模块,可以满足我的需求.

app/models/shared/attachment_helper.rb以内:

module Shared
  module AttachmentHelper

    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      def has_attachment(name, options = {})

        # generates a string containing the singular model name and the pluralized attachment name.
        # Examples: "user_avatars" or "asset_uploads" or "message_previews"
        attachment_owner    = self.table_name.singularize
        attachment_folder   = "#{attachment_owner}_#{name.to_s.pluralize}"

        # we want to create a path for the upload that looks like:
        # message_previews/00/11/22/001122deadbeef/thumbnail.png
        attachment_path     = "#{attachment_folder}/:uuid_partition/:uuid/:style.:extension"

        if Rails.env.production?
          options[:path]            ||= attachment_path
          options[:storage]         ||= :s3
          options[:url]             ||= ':s3_authenticated_url'
          options[:s3_credentials]  ||= File.join(Rails.root, 'config', 's3.yml')
          options[:s3_permissions]  ||= 'private'
          options[:s3_protocol]     ||= 'https'
        else
          # For local Dev/Test envs, use the default filesystem, but separate the environments
          # into different folders, so you can delete test files without breaking dev files.
          options[:path]  ||= ":rails_root/public/system/attachments/#{Rails.env}/#{attachment_path}"
          options[:url]   ||= "/system/attachments/#{Rails.env}/#{attachment_path}"
        end

        # pass things off to paperclip.
        has_attached_file name, options
      end
    end
  end
end

(Note: I'm using some custom paperclip interpolations above, like 100, 101 and 102. You'll need to modify things as needed for your particular application)

现在,对于每个有回形针附件的模型,你只需要包含这个共享模块,并调用has_attachment方法(而不是回形针的has_attached_file)

示例模型文件:app/models/user.rb:

class User < ActiveRecord::Base
  include Shared::AttachmentHelper  
  has_attachment :avatar, :styles => { :thumbnail => "100x100>" }
end

有了这个选项,根据您的环境,您可以将文件保存到以下位置:

Development:

RAILS_ROOT + public/attachments/development/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg

Test:

RAILS_ROOT + public/attachments/test/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg

Production:

https://s3.amazonaws.com/your-bucket-name/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg

这正是我想要的,希望它对其他人也有用.:)

-约翰

Ruby-on-rails相关问答推荐

HTTP:MimeNegotiation::InvalidType(html不是有效的MIME类型):""

Ruby on Rails - 外键不匹配

has_many 通过大小验证

Rspec期望()与期望{}

在一行中更改多个对象属性

Rails 3:如何正确显示textarea中的文本?

将 defer 属性添加到 javascript_include_tag Rails

Rails:如何在表单的必填字段上禁用星号?

在本地 Rails 开发环境中获取真实 IP 地址

在 ruby​​ 中构建公钥时,是什么导致既不是 PUB key 也不是 PRIV key::nested asn1 错误?

Groovy/Grails :: Ruby/Rails :: 2011 框架状态

rails active admin 部署:找不到文件'jquery-ui'

如何为 rspec 设置 ENV 变量?

Rails 3.1 中的 Rails.cache 错误 - TypeError: can't dump hash with default proc

Dotenv 多行变量

Rails 生成 has_many 关联

如何更改 Rails 3 控制器中视图文件的默认路径?

ActiveRecord 查找以

如何测试也定义为辅助方法的 ApplicationController 方法?

在 Rails 4.1 中,如何通过枚举符号查找记录?