Pertanyaan Bagaimana saya bisa mengatur mekanisme penyimpanan paperclip berdasarkan lingkungan Rails saat ini?


Saya memiliki aplikasi rel yang memiliki beberapa model dengan lampiran penjepit kertas yang semuanya diunggah ke S3. Aplikasi ini juga memiliki rangkaian uji besar yang cukup sering dijalankan. Kelemahannya adalah bahwa satu ton file diunggah ke akun S3 kami pada setiap uji coba, membuat rangkaian uji berjalan lambat. Ini juga memperlambat pengembangan sedikit, dan mengharuskan Anda untuk memiliki koneksi internet untuk bekerja pada kode.

Apakah ada cara yang masuk akal untuk mengatur mekanisme penyimpanan klip kertas berdasarkan lingkungan Rails? Idealnya, lingkungan pengujian dan pengembangan kami akan menggunakan penyimpanan filesystem lokal, dan lingkungan produksi akan menggunakan penyimpanan S3.

Saya juga ingin mengekstrak logika ini ke dalam modul bersama, karena kami memiliki beberapa model yang akan membutuhkan perilaku ini. Saya ingin menghindari solusi seperti ini di dalam setiap 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

Memperbarui: Bagian yang lengket adalah bahwa lampiran itu :path dan :url pilihan harus berbeda tergantung pada sistem penyimpanan yang digunakan.

Setiap saran atau saran akan sangat dihargai! :-)


75
2018-04-01 17:18


asal


Jawaban:


Saya lebih menyukai saran Barry dan tidak ada yang menghalangi Anda untuk mengatur variabel menjadi hash, yang kemudian dapat digabungkan dengan opsi penjepit kertas.

Dalam config / environment / development.rb dan test.rb atur sesuatu seperti

PAPERCLIP_STORAGE_OPTIONS = {}

Dan di config / environment / production.rb

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

Akhirnya dalam model penjepit kertas Anda:

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

Memperbarui: Pendekatan serupa baru-baru ini diimplementasikan dalam Paperclip untuk aplikasi Rails 3.x. Pengaturan spesifik lingkungan sekarang dapat diatur dengan config.paperclip_defaults = {:storage => :s3, ...}.


78
2017-08-10 20:22



Anda dapat mengatur data konfigurasi default global dalam file konfigurasi khusus lingkungan. Misalnya, di config / environment / 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



Setelah bermain-main dengan itu untuk sementara waktu, saya datang dengan modul yang melakukan apa yang saya inginkan.

Dalam 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

(Catatan: Saya menggunakan beberapa interpolasi klip kertas kustom di atas, seperti :uuid_partition, :uuid dan :s3_authenticated_url. Anda harus memodifikasi hal-hal yang diperlukan untuk aplikasi khusus Anda)

Sekarang, untuk setiap model yang memiliki lampiran penjepit kertas, Anda hanya perlu menyertakan modul bersama ini, dan panggil has_attachment metode (bukan penjepit kertas has_attached_file)

Contoh file model: app/models/user.rb:

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

Dengan ini di tempat, Anda akan memiliki file yang disimpan ke lokasi berikut, tergantung pada lingkungan Anda:

Pengembangan: 

RAILS_ROOT + public/attachments/development/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg

Uji:

RAILS_ROOT + public/attachments/test/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg

Produksi:

https://s3.amazonaws.com/your-bucket-name/user_avatars/aa/bb/cc/aabbccddeeff/thumbnail.jpg

Ini persis apa yang saya cari, semoga itu juga bermanfaat bagi orang lain. :)

-John


27
2018-04-02 19:23



Bagaimana dengan ini:

  1. Default ditetapkan dalam application.rb. Penyimpanan default: filesystem digunakan, tetapi konfigurasi untuk s3 diinisialisasi
  2. Production.rb memungkinkan: penyimpanan s3 dan mengubah jalur default

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 (hapus komentar ini untuk mencoba dengan s3 dalam mode pengembangan)

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

Production.rb:

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

Dalam model Anda:

has_attached_file :avatar 

5
2018-06-22 18:54



Tidak bisakah Anda menetapkan variabel lingkungan dalam produksi / uji / pengembangan.rb?

PAPERCLIP_STORAGE_MECHANISM = :s3

Kemudian:

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

2
2018-04-01 17:56



Solusi saya sama dengan jawaban @runesoerensen:

Saya membuat modul PaperclipStorageOption di config/initializers/paperclip_storage_option.rb Kode ini sangat sederhana:

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

dan menggunakannya dalam model kami has_attached_file :avatar, { :styles => { :medium => "1200x800>" } }.merge(PaperclipStorageOption.options)

Hanya itu, harap bantuan ini


0
2018-02-17 03:55



Gunakan: interpolasi rails_env ketika Anda menentukan jalur lampiran:

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

-4
2018-01-18 10:39