如何根据当前的Rails环境设置回形针的存储机制? [英] How can I set paperclip's storage mechanism based on the current Rails environment?

查看:19
本文介绍了如何根据当前的Rails环境设置回形针的存储机制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 rails 应用程序,它有多个模型,所有模型都上传到 S3 的回形针附件.这个应用程序还有一个经常运行的大型测试套件.这样做的缺点是每次测试运行时都会将大量文件上传到我们的 S3 帐户,从而导致测试套件运行缓慢.它也会稍微减慢开发速度,并且需要您具有 Internet 连接才能处理代码.

I have a rails application that has multiple models with paperclip attachments that are all uploaded to S3. This app also has a large test suite that is run quite often. The downside with this is that a ton of files are uploaded to our S3 account on every test run, making the test suite run slowly. It also slows down development a bit, and requires you to have an internet connection in order to work on the code.

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

Is there a reasonable way to set the paperclip storage mechanism based on the Rails environment? Ideally, our test and development environments would use the local filesystem storage, and the production environment would use S3 storage.

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

I'd also like to extract this logic into a shared module of some kind, since we have several models that will need this behavior. I'd like to avoid a solution like this inside of every model:

### 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

更新: 棘手的部分是附件的 :path:url 选项需要根据所使用的存储系统而有所不同.

Update: The sticky part is that the attachment's :path and :url options need to differ depending on which storage system is being used.

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

Any advice or suggestions would be greatly appreciated! :-)

推荐答案

在玩了一段时间后,我想出了一个可以做我想做的模块.

After playing around with it for a while, I came up with a module that does what I want.

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

(注意:我在上面使用了一些自定义回形针插值,例如 :uuid_partition:uuid:s3_authenticated_url.您需要根据特定应用程序的需要进行修改)

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

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

Now, for every model that has paperclip attachments, you just have to include this shared module, and call the has_attachment method (instead of paperclip's has_attached_file)

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

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

完成此操作后,您会将文件保存到以下位置,具体取决于您的环境:

With this in place, you'll have files saved to the following locations, depending on your environment:

开发:

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

测试:

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

生产:

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

这正是我正在寻找的,希望它也能对其他人有用.:)

This does exactly what I'm looking for, hopefully it'll prove useful to someone else too. :)

-约翰

这篇关于如何根据当前的Rails环境设置回形针的存储机制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆