program tip

현재 Rails 환경을 기반으로 종이 클립의 저장 메커니즘을 어떻게 설정할 수 있습니까?

radiobox 2020. 10. 19. 07:54
반응형

현재 Rails 환경을 기반으로 종이 클립의 저장 메커니즘을 어떻게 설정할 수 있습니까?


S3에 모두 업로드되는 클립 첨부 파일이있는 여러 모델이있는 Rails 애플리케이션이 있습니다. 이 앱에는 매우 자주 실행되는 대규모 테스트 도구 모음도 있습니다. 단점은 테스트를 실행할 때마다 S3 계정에 수많은 파일이 업로드되어 테스트 스위트가 느리게 실행된다는 것입니다. 또한 개발 속도가 약간 느려지고 코드 작업을 위해 인터넷 연결이 필요합니다.

Rails 환경을 기반으로 종이 클립 저장 메커니즘을 설정하는 합리적인 방법이 있습니까? 이상적으로는 테스트 및 개발 환경은 로컬 파일 시스템 스토리지를 사용하고 프로덕션 환경은 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옵션 이 달라야한다는 것 입니다.

어떤 조언이나 제안이라도 대단히 감사하겠습니다! :-)


나는 Barry의 제안을 더 좋아하고 변수를 해시로 설정하는 것을 막을 수있는 것은 없습니다. 그런 다음 종이 클립 옵션과 병합 할 수 있습니다.

config / environments / development.rb 및 test.rb에서 다음과 같이 설정하십시오.

PAPERCLIP_STORAGE_OPTIONS = {}

그리고 config / environments / production.rb

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)

업데이트 : 최근 Rails 3.x 앱용 Paperclip에서 유사한 접근 방식이 구현되었습니다 . 이제 환경 별 설정을 config.paperclip_defaults = {:storage => :s3, ...}.


환경 별 구성 파일에서 전역 기본 구성 데이터를 설정할 수 있습니다. 예를 들어, 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']
  }
})

한동안 가지고 놀다가 내가 원하는 것을하는 모듈을 생각 해냈다.

내부 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메서드를 호출하면 됩니다 (paperclip 대신 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

이것은 내가 찾고있는 것을 정확히 수행하며, 다른 사람에게도 유용 할 것입니다. :)

-남자


이것은 어떤가요:

  1. 기본값은 application.rb에 설정됩니다. : filesystem의 기본 저장소가 사용되지만 s3에 대한 구성이 초기화됩니다.
  2. Production.rb는 : s3 스토리지를 활성화하고 기본 경로를 변경합니다.

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 (개발 모드에서 s3로 시도하려면 주석 처리를 제거하십시오)

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

Production.rb :

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

모델에서 :

has_attached_file :avatar 

production / test / development.rb에서 환경 변수를 설정할 수 없습니까?

PAPERCLIP_STORAGE_MECHANISM = :s3

그때:

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

내 솔루션은 @runesoerensen 답변과 동일합니다.

나는 모듈 생성 PaperclipStorageOptionconfig/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)

Just it, hope this help


Use the :rails_env interpolation when you define the attachment path:

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

참고URL : https://stackoverflow.com/questions/2562249/how-can-i-set-paperclips-storage-mechanism-based-on-the-current-rails-environme

반응형