Frage Wie kann ich den Speichermechanismus von Paperclip basierend auf der aktuellen Rails-Umgebung einstellen?


Ich habe eine Schienenanwendung, die mehrere Modelle mit Büroklammeranhängen hat, die alle auf S3 hochgeladen wurden. Diese App hat auch eine große Testsuite, die oft ausgeführt wird. Der Nachteil dabei ist, dass eine Tonne von Dateien bei jedem Testlauf auf unseren S3-Account hochgeladen wird, wodurch die Testsuite langsam läuft. Es verlangsamt auch die Entwicklung ein bisschen und erfordert, dass Sie eine Internetverbindung haben, um an dem Code zu arbeiten.

Gibt es eine vernünftige Möglichkeit, den Büroklammerspeichermechanismus basierend auf der Rails-Umgebung einzurichten? Idealerweise würden unsere Test- und Entwicklungsumgebungen den lokalen Dateisystemspeicher verwenden, und die Produktionsumgebung würde S3-Speicher verwenden.

Ich möchte diese Logik auch in ein geteiltes Modul irgendeiner Art 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

Aktualisieren: Der klebrige Teil ist der der Anhänge :path und :url Optionen müssen sich unterscheiden, je nachdem, welches Speichersystem verwendet wird.

Jeder Rat oder Vorschläge würde sehr geschätzt werden! :-)


75
2018-04-01 17:18


Ursprung


Antworten:


Ich mag Barrys Vorschlag besser und es gibt nichts, was Sie davon abhält, die Variable auf einen Hashwert zu setzen, der dann mit den Büroklammeroptionen zusammengeführt werden kann.

In config / environments / development.rb und test.rb legen Sie so etwas fest

PAPERCLIP_STORAGE_OPTIONS = {}

Und in config / environments / production.rb

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

Schließlich in Ihrem Büroklammermodell:

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

Aktualisieren: Ein ähnlicher Ansatz wurde kürzlich verfolgt in Paperclip implementiert für Rails 3.x Apps. Umgebungsspezifische Einstellungen können jetzt mit eingestellt werden config.paperclip_defaults = {:storage => :s3, ...}.


78
2017-08-10 20:22



Sie können globale Standardkonfigurationsdaten in den umgebungsspezifischen Konfigurationsdateien festlegen. Zum Beispiel in 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']
  }
})

32
2018-06-11 01:42



Nachdem ich eine Weile damit herumgespielt habe, habe ich mir ein Modul ausgedacht, das genau das macht, was ich will.

Innerhalb 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

(Hinweis: Ich verwende einige benutzerdefinierte Papierclip Interpolationen oben, wie :uuid_partition, :uuid und :s3_authenticated_url. Sie müssen die Dinge ändern, wie für Ihre spezielle Anwendung benötigt)

Jetzt müssen Sie für jedes Modell, das über Büroklammern verfügt, nur dieses freigegebene Modul hinzufügen und die has_attachment Methode (anstelle von Büroklammern has_attached_file)

Eine Beispielmodelldatei: app/models/user.rb:

class User < ActiveRecord::Base
  include Shared::AttachmentHelper  
  has_attachment :avatar, :styles => { :thumbnail => "100x100>" }
end

Wenn Sie diese Funktion aktiviert haben, werden die 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

Das macht genau das, was ich suche, hoffentlich wird es sich auch für jemand anderen als nützlich erweisen. :)

-John


27
2018-04-02 19:23



Wie wäre es damit:

  1. Die Standardeinstellungen sind in application.rb festgelegt. Der Standardspeicher von: filesystem wird verwendet, aber die Konfiguration für s3 wird initialisiert
  2. Production.rb ermöglicht: s3 Speicher und ändert den Standardpfad

Anwendung.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 (Kommentar auskommentieren mit s3 im Entwicklungsmodus)

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

Produktion.rb:

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

In Ihrem Modell:

has_attached_file :avatar 

5
2018-06-22 18:54



Könnten Sie nicht einfach eine Umgebungsvariable in production / test / development.rb setzen?

PAPERCLIP_STORAGE_MECHANISM = :s3

Dann:

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

2
2018-04-01 17:56



Meine Lösung ist dieselbe mit @runesoerensen Antwort:

Ich erstelle ein Modul PaperclipStorageOption im config/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 benutze es in unserem Modell has_attached_file :avatar, { :styles => { :medium => "1200x800>" } }.merge(PaperclipStorageOption.options)

Nur, hoffe diese Hilfe


0
2018-02-17 03:55



Verwenden Sie die interfaces rails_env, wenn Sie den Anhangspfad definieren:

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

-4
2018-01-18 10:39