[英]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: 这个怎么样:
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.