Ich habe eine Rails-Anwendung mit mehreren Modellen mit Büroklammeranhängen, die alle in S3 hochgeladen werden. Diese App hat auch eine große Testsuite, die ziemlich oft ausgeführt wird. Der Nachteil dabei ist, dass bei jedem Testlauf eine Menge Dateien auf unser S3-Konto hochgeladen werden, wodurch die Testsuite langsam ausgeführt wird. Es verlangsamt auch die Entwicklung ein wenig und erfordert eine Internetverbindung, um an dem Code arbeiten zu können.
Gibt es eine vernünftige Möglichkeit, den Büroklammer-Speichermechanismus basierend auf der Rails-Umgebung festzulegen? Im Idealfall verwenden unsere Test- und Entwicklungsumgebungen den lokalen Dateisystemspeicher und die Produktionsumgebung S3-Speicher.
Ich möchte diese Logik auch in ein gemeinsames Modul extrahieren, da wir mehrere Modelle haben, die dieses Verhalten benötigen. Ich möchte eine solche Lösung in jedem Modell vermeiden:
### 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: Der entscheidende Teil ist, dass die Anhänge :path
und :url
Optionen je nach verwendetem Speichersystem unterschiedlich sein müssen.
Jeder Rat oder Anregungen wäre sehr dankbar! :-)
quelle
Nachdem ich eine Weile damit herumgespielt hatte, kam ich auf ein Modul, das macht, was ich will.
Innen
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
(Anmerkung: Ich verwende einige benutzerdefinierte Büroklammer Einschübe oben, wie
:uuid_partition
,:uuid
und:s3_authenticated_url
Sie werden die Dinge ändern müssen , wie für die jeweilige Anwendung benötigt wird .)Jetzt müssen Sie für jedes Modell mit Büroklammeranhängen nur noch dieses freigegebene Modul einschließen und die
has_attachment
Methode aufrufen (anstelle der Büroklammernhas_attached_file
).Ein Beispiel Modelldatei:
app/models/user.rb
:class User < ActiveRecord::Base include Shared::AttachmentHelper has_attachment :avatar, :styles => { :thumbnail => "100x100>" } end
Mit dieser Option werden Dateien abhängig von Ihrer Umgebung an den folgenden Speicherorten gespeichert:
Entwicklung:
RAILS_ROOT + public/attachments/development/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg
Prüfung:
RAILS_ROOT + public/attachments/test/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg
Produktion:
https://s3.amazonaws.com/your-bucket-name/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg
Dies macht genau das, wonach ich suche, hoffentlich wird es sich auch für jemand anderen als nützlich erweisen. :) :)
-John
quelle
Wie wäre es damit:
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 (kommentieren Sie dies aus, um es mit s3 im Entwicklungsmodus zu versuchen)
# config.paperclip_defaults.merge!({ # :storage => :s3, # :bucket => "mydevelopmentbucket", # :path => ":hash.:extension" # })
Production.rb:
config.paperclip_defaults.merge!({ :storage => :s3, :bucket => "myproductionbucket", :path => ":hash.:extension" })
In Ihrem Modell:
has_attached_file :avatar
quelle
Könnten Sie nicht einfach eine Umgebungsvariable in Production / Test / Development.rb festlegen?
PAPERCLIP_STORAGE_MECHANISM = :s3
Dann:
has_attached_file :image, :styles => {...}, :storage => PAPERCLIP_STORAGE_MECHANISM, # ...etc...
quelle
Meine Lösung ist dieselbe mit der Antwort von @runesoerensen:
Ich erstelle ein Modul
PaperclipStorageOption
inconfig/initializers/paperclip_storage_option.rb
Der Code ist sehr einfach: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
und verwenden Sie es in unserem Modell
has_attached_file :avatar, { :styles => { :medium => "1200x800>" } }.merge(PaperclipStorageOption.options)
Nur es, hoffe diese Hilfe
quelle
Verwenden Sie die Interpolation: rails_env, wenn Sie den Anhangspfad definieren:
has_attached_file :attachment, :path => ":rails_root/storage/:rails_env/attachments/:id/:style/:basename.:extension"
quelle