如何根据当前的Rails环境设置回形针的存储机制?

Joh*_*lly 75 ruby-on-rails amazon-s3 paperclip

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

有没有合理的方法来设置基于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
Run Code Online (Sandbox Code Playgroud)

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

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

run*_*sen 78

我更喜欢Barry的建议,并且没有什么能阻止您将变量设置为哈希值,然后可以将其与回形针选项合并.

在config/environments/development.rb和test.rb中设置类似的东西

PAPERCLIP_STORAGE_OPTIONS = {}
Run Code Online (Sandbox Code Playgroud)

在config/environments/production.rb中

PAPERCLIP_STORAGE_OPTIONS = {:storage => :s3, 
                               :s3_credentials => "#{Rails.root}/config/s3.yml",
                               :path => "/:style/:filename"}
Run Code Online (Sandbox Code Playgroud)

最后在你的回形针模型中:

has_attached_file :image, {
    :styles => {:thumb => '50x50#', :original => '800x800>'}
}.merge(PAPERCLIP_STORAGE_OPTIONS)
Run Code Online (Sandbox Code Playgroud)

更新:最近在Paperclip for Rails 3.x应用程序中实现了类似的方法.现在可以使用设置环境特定设置config.paperclip_defaults = {:storage => :s3, ...}.


aus*_*ton 32

您可以在特定于环境的配置文件中设置全局默认配置数据.例如,在config/environments/production.rb中:

Paperclip::Attachment.default_options.merge!({
  :storage => :s3,
  :bucket => 'wheresmahbucket',
  :s3_credentials => {
    :access_key_id => ENV['S3_ACCESS_KEY_ID'],
    :secret_access_key => ENV['S3_SECRET_ACCESS_KEY']
  }
})
Run Code Online (Sandbox Code Playgroud)


Joh*_*lly 27

在玩了一会儿之后,我想出了一个可以满足我想要的模块.

内部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
Run Code Online (Sandbox Code Playgroud)

(注意:我正在使用上面的一些自定义回形针插值,比如:uuid_partition,:uuid:s3_authenticated_url.你需要根据特定应用的需要修改内容)

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

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

class User < ActiveRecord::Base
  include Shared::AttachmentHelper  
  has_attachment :avatar, :styles => { :thumbnail => "100x100>" }
end
Run Code Online (Sandbox Code Playgroud)

有了这个,您将把文件保存到以下位置,具体取决于您的环境:

发展:

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

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

-约翰


Joh*_*gle 5

这个怎么样:

  1. 默认值在application.rb中建立.使用默认存储:filesystem,但初始化s3的配置
  2. Production.rb启用:s3存储并更改默认路径

application.rb中

config.paperclip_defaults = 
{
  :hash_secret => "LongSecretString",
  :s3_protocol => "https",
  :s3_credentials => "#{Rails.root}/config/aws_config.yml",
  :styles => { 
    :original => "1024x1024>",
    :large => "600x600>", 
    :medium => "300x300>",
    :thumb => "100x100>" 
  }
}
Run Code Online (Sandbox Code Playgroud)

Development.rb(在开发模式下取消注释以尝试使用s3)

# config.paperclip_defaults.merge!({
#   :storage => :s3,
#   :bucket => "mydevelopmentbucket",
#   :path => ":hash.:extension"
# })
Run Code Online (Sandbox Code Playgroud)

Production.rb:

config.paperclip_defaults.merge!({
  :storage => :s3,
  :bucket => "myproductionbucket",
  :path => ":hash.:extension"
})
Run Code Online (Sandbox Code Playgroud)

在你的模型中:

has_attached_file :avatar 
Run Code Online (Sandbox Code Playgroud)