Как я могу установить механизм хранения скрепки на основе текущей среды Rails?
у меня есть приложение rails, которое имеет несколько моделей с вложениями скрепки, которые все загружены в S3. Это приложение также имеет большой набор тестов, который выполняется довольно часто. Недостатком этого является то, что тонна файлов загружается в нашу учетную запись S3 при каждом тестовом запуске, что заставляет тестовый набор работать медленно. Это также немного замедляет разработку и требует, чтобы у вас было подключение к интернету для работы над кодом.
есть ли разумный способ установить скрепку механизм хранения основанный на окружающей среде рельсов? В идеале, наши среды тестирования и разработки будут использовать локальное хранилище файловой системы, а производственная среда будет использовать хранилище 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
обновление: липкая часть заключается в том, что вложения :path
и :url
опции должны отличаться в зависимости от того, какая система хранения используется.
любые советы или предложения будут с благодарностью! : -)
7 ответов:
мне больше нравится предложение Барри, и ничто не мешает вам установить переменную в хэш, который затем можно объединить с параметрами скрепки.
в config / environments / development.РБ и тест.РБ установить что-то вроде
PAPERCLIP_STORAGE_OPTIONS = {}
и в config / environments / production.РБ
PAPERCLIP_STORAGE_OPTIONS = {:storage => :s3, :s3_credentials => "#{Rails.root}/config/s3.yml", :path => "/:style/:filename"}
наконец-то в вашей модели скрепки:
has_attached_file :image, { :styles => {:thumb => '50x50#', :original => '800x800>'} }.merge(PAPERCLIP_STORAGE_OPTIONS)
обновление: подобный подход был недавно выполнены в Скрепка для рельсов 3.x приложения. Настройки для конкретной среды теперь можно установить с помощью
config.paperclip_defaults = {:storage => :s3, ...}
.
вы можете установить глобальные данные конфигурации по умолчанию в файлах конфигурации конкретной среды. Например, в config / environments / production.РБ:
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'] } })
поиграв с ним некоторое время, я придумал модуль, который делает то, что я хочу.
внутри
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
. Вам нужно будет изменить вещи по мере необходимости для вашего конкретного приложения)теперь для каждой модели, которая имеет вложения скрепки, вы просто должны включить этот общий модуль и вызвать
has_attachment
метод (вместо скрепкиhas_attached_file
)пример файла модели:
app/models/user.rb
:class User < ActiveRecord::Base include Shared::AttachmentHelper has_attachment :avatar, :styles => { :thumbnail => "100x100>" } end
С этим на месте, вы будете иметь файлы, сохраненные в следующих местах, в зависимости от вашей среды:
развитие:
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
это именно то, что Я ищу, надеюсь, это окажется полезным для кого-то еще тоже. :)
-Джон
как насчет этого:
- по умолчанию устанавливаются в приложении.рубидий. Хранилище по умолчанию :файловая система используется, но конфигурация для s3 инициализируется
- производства.rb включает: хранение s3 и изменяет путь по умолчанию
приложение.РБ
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>" } }
развитие.rb (раскомментируйте это, чтобы попробовать с s3 в режиме разработки)
# config.paperclip_defaults.merge!({ # :storage => :s3, # :bucket => "mydevelopmentbucket", # :path => ":hash.:extension" # })
производства.РБ:
config.paperclip_defaults.merge!({ :storage => :s3, :bucket => "myproductionbucket", :path => ":hash.:extension" })
В вашей модель:
has_attached_file :avatar
не могли бы вы просто установить переменную среды в production/test/development.РБ?
PAPERCLIP_STORAGE_MECHANISM = :s3
затем:
has_attached_file :image, :styles => {...}, :storage => PAPERCLIP_STORAGE_MECHANISM, # ...etc...
мое решение то же самое с @runesoerensen ответ:
Я создаю модуль
PaperclipStorageOption
inconfig/initializers/paperclip_storage_option.rb
Код очень простой: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
и использовать его в нашей модели
has_attached_file :avatar, { :styles => { :medium => "1200x800>" } }.merge(PaperclipStorageOption.options)
просто это, надеюсь, что это поможет