75 votes

Comment définir le mécanisme de stockage d'un trombone en fonction de l'environnement Rails actuel?

J'ai une application rails qui a plusieurs modèles avec un trombone, des pièces jointes qui sont tous téléchargée sur S3. Cette application dispose également d'une grande suite de test qui est exécuté assez souvent. L'inconvénient de ceci est que une tonne de fichiers sont téléchargés dans notre S3 compte sur chaque série de tests, faisant de la suite de tests de courir lentement. Il ralentit aussi le développement un peu, et vous oblige à avoir une connexion internet pour travailler sur le code.

Est-il raisonnable de façon à définir la forme de trombone mécanisme de stockage basé sur les Rails de l'environnement? Idéalement, notre test et les environnements de développement serait d'utiliser le système de fichiers local de stockage, et de l'environnement de production serait de l'utiliser de stockage S3.

Je tiens également à extraire de cette logique dans un module partagé d'une certaine sorte, puisque nous avons plusieurs modèles qui auront besoin de ce comportement. Je voudrais éviter une solution à ceci à l'intérieur de chaque modèle:

### 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

Mise à jour: Le collant, c'est que la pièce jointe :path et :url des options diffèrent selon le système de stockage est utilisé.

Tous les conseils ou suggestions seraient grandement appréciés! :-)

78voto

runesoerensen Points 2596

J'aime Barry suggestion du mieux et il n'y a rien qui vous retient de définition de la variable à une valeur de hachage, qui peut ensuite être fusionné avec le trombone options.

Dans config/environments/développement.rb et de test.rb mis quelque chose comme

PAPERCLIP_STORAGE_OPTIONS = {}

Et dans config/environments/production.rb

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

Enfin dans votre trombone modèle:

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

Mise à jour: Une approche similaire a été récemment mis en œuvre en forme de Trombone pour Rails 3.x des applications. Environnement spécifique, les paramètres peuvent être définis avec config.paperclip_defaults = {:storage => :s3, ...}.

32voto

austinfromboston Points 3174

Vous pouvez définir des données de configuration globales par défaut dans les fichiers de configuration spécifiques à l'environnement. Par exemple, dans config / environnements / 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']
  }
})
 

27voto

John Reilly Points 912

Après avoir joué avec lui pendant un moment, je suis venu avec un module qui fait ce que je veux.

À l'intérieur d' 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

(Note: je suis à l'aide de coutume, un trombone, des interpolations ci-dessus, comme :uuid_partition, :uuid et :s3_authenticated_url. Vous aurez besoin de modifier les choses comme il faut pour votre application particulière)

Maintenant, pour chaque modèle de trombone, les pièces jointes, il vous suffit d'inclure ce module partagé, et d'appeler l' has_attachment méthode (au lieu de trombone de l' has_attached_file)

Un exemple de fichier de modèle: app/models/user.rb:

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

Dans ce lieu, vous aurez les fichiers enregistrés dans les emplacements suivants, en fonction de votre environnement:

Développement:

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

Test:

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

Production:

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

C'est exactement ce que je suis à la recherche pour, espérons-le, il va s'avérer utile à quelqu'un d'autre aussi. :)

-Jean

5voto

John Naegle Points 2180

Comment à ce sujet:

  1. Les valeurs par défaut sont établies en application.rb. Le défaut de stockage de l' :le système de fichiers est utilisé, mais la configuration pour le s3 est initialisé
  2. De Production.rb permet de :stockage s3 et modifie le chemin d'accès par défaut

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>" 
  }
}

Développement.rb (décommentez la ligne suivante pour essayer avec le s3, le mode de développement)

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

De Production.rb:

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

Dans votre modèle:

has_attached_file :avatar 

2voto

Barry Hess Points 492

Ne pourriez-vous pas simplement définir une variable d'environnement dans production / test / development.rb?

 PAPERCLIP_STORAGE_MECHANISM = :s3
 

Ensuite:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X