简体   繁体   English

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

[英]How can I set paperclip's storage mechanism based on the current Rails environment?

I have a rails application that has multiple models with paperclip attachments that are all uploaded to S3. 我有一个rails应用程序,它有多个带有回形针附件的模型,这些附件都上传到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. 这样做的缺点是每次测试运行都会将大量文件上传到我们的S3帐户,这使得测试套件运行缓慢。 It also slows down development a bit, and requires you to have an internet connection in order to work on the code. 它还会降低开发速度,并要求您具有Internet连接以便处理代码。

Is there a reasonable way to set the paperclip storage mechanism based on the Rails environment? 有没有合理的方法来设置基于Rails环境的回形针存储机制? Ideally, our test and development environments would use the local filesystem storage, and the production environment would use S3 storage. 理想情况下,我们的测试和开发环境将使用本地文件系统存储,生产环境将使用S3存储。

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

Update: The sticky part is that the attachment's :path and :url options need to differ depending on which storage system is being used. 更新:粘性部分是附件的:path:url选项需要根据使用的存储系统而有所不同。

Any advice or suggestions would be greatly appreciated! 任何建议或建议将不胜感激! :-) :-)

I like Barry's suggestion better and there's nothing keeping you from setting the variable to a hash, that can then be merged with the paperclip options. 我更喜欢Barry的建议,并且没有什么能阻止您将变量设置为哈希值,然后可以将其与回形针选项合并。

In config/environments/development.rb and test.rb set something like 在config / environments / development.rb和test.rb中设置类似的东西

PAPERCLIP_STORAGE_OPTIONS = {}

And in config/environments/production.rb 在config / environments / production.rb中

PAPERCLIP_STORAGE_OPTIONS = {:storage => :s3, 
                               :s3_credentials => "#{Rails.root}/config/s3.yml",
                               :path => "/:style/:filename"}

Finally in your paperclip model: 最后在你的回形针模型中:

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

Update: A similar approach was recently implemented in Paperclip for Rails 3.x apps. 更新:最近在Paperclip for Rails 3.x应用程序中实现了类似的方法。 Environment specific settings can now be set with config.paperclip_defaults = {:storage => :s3, ...} . 现在可以使用config.paperclip_defaults = {:storage => :s3, ...}设置特定于环境的设置。

You can set global default configuration data in the environment-specific configuration files. 您可以在特定于环境的配置文件中设置全局默认配置数据。 For example, in config/environments/production.rb: 例如,在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']
  }
})

After playing around with it for a while, I came up with a module that does what I want. 在玩了一会儿之后,我想出了一个可以满足我想要的模块。

Inside app/models/shared/attachment_helper.rb : 内部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 :uuid_partition , :uuid and :s3_authenticated_url . You'll need to modify things as needed for your particular application) (注意:我正在使用上面的一些自定义回形针插值,例如:uuid_partition:uuid:s3_authenticated_url 。您需要根据特定应用的需要修改内容)

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 ) 现在,对于每个具有回形针附件的模型,您只需要包含此共享模块,并调用has_attachment方法(而不是paperclip的has_attached_file

An example model file: app/models/user.rb : 示例模型文件: 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: 有了这个,您将把文件保存到以下位置,具体取决于您的环境:

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

This does exactly what I'm looking for, hopefully it'll prove useful to someone else too. 这正是我正在寻找的东西,希望它对其他人也有用。 :) :)

-John -约翰

How about this: 这个怎么样:

  1. Defaults are established in application.rb. 默认值在application.rb中建立。 The default storage of :filesystem is used, but the configuration for s3 is initialized 使用默认存储:filesystem,但初始化s3的配置
  2. Production.rb enables :s3 storage and changes the default path Production.rb启用:s3存储并更改默认路径

Application.rb 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>" 
  }
}

Development.rb (uncomment this to try with s3 in development mode) Development.rb(取消注释以在开发模式下尝试使用s3)

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

Production.rb: Production.rb:

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

In your model: 在你的模型中:

has_attached_file :avatar 

Couldn't you just set an environment variable in production/test/development.rb? 难道你不能在production / test / development.rb中设置一个环境变量吗?

PAPERCLIP_STORAGE_MECHANISM = :s3

Then: 然后:

has_attached_file :image, :styles => {...},
                  :storage => PAPERCLIP_STORAGE_MECHANISM,
                  # ...etc...

My solution is same with @runesoerensen answer: 我的解决方案与@runesoerensen的答案相同:

I create a module PaperclipStorageOption in config/initializers/paperclip_storage_option.rb The code is very simple: 我在config/initializers/paperclip_storage_option.rb PaperclipStorageOption中创建了一个模块PaperclipStorageOption 。代码非常简单:

module PaperclipStorageOption
  module ClassMethods
    def options
      Rails.env.production? ? production_options : default_options
    end

    private

    def production_options
      {
        storage: :dropbox,
        dropbox_credentials: Rails.root.join("config/dropbox.yml")
      }
    end

    def default_options
      {}
    end
  end

  extend ClassMethods
end

and use it in our model has_attached_file :avatar, { :styles => { :medium => "1200x800>" } }.merge(PaperclipStorageOption.options) 并在我们的模型中使用它has_attached_file :avatar, { :styles => { :medium => "1200x800>" } }.merge(PaperclipStorageOption.options)

Just it, hope this help 就这样,希望这有帮助

定义附件路径时使用:rails_env插值:

has_attached_file :attachment, :path => ":rails_root/storage/:rails_env/attachments/:id/:style/:basename.:extension"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以使用Paperclip在Rails中发表评论吗? - Can I use Paperclip for comments in rails and how? Rails 3和Paperclip-我可以在S3或本地存储图像吗? - Rails 3 & Paperclip - Can I store images both on S3 & locally? 如何将CarrierWave文件迁移到新的存储机制? - How can I migrate CarrierWave files to a new storage mechanism? 如何在 Rails / Paperclip / S3 上更新 Ruby 中的文件? - How can you update a file in Ruby on Rails / Paperclip / S3? 如何从s3上的文件而不是表单中设置回形针宝石图像数据? - How can I set Paperclip Gem image data from a file on s3, instead of from a form? Rails:如何使用当前参数设置空数组 - Rails: How can i set empty array with current parameters 如何优化使用Paperclip&Rails上传的图像? - How can I optimize images uploaded using Paperclip & Rails? 禁用校验和导轨活动存储回形针迁移AWS S3 - disable checksum rails active storage paperclip migration aws s3 S3回形针导轨无法显示图像 - S3 Paperclip rails Can not display image Rails Paperclip和AWS s3集成错误“未初始化的常量Paperclip :: Storage :: S3 :: Aws” - Rails Paperclip and aws s3 integration error “uninitialized constant Paperclip::Storage::S3::Aws”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM