paperclipでS3にファイルアップロードするアプリ

前提として、S3を契約している必要があります


まずは、environment.rbに以下を追加します

config.gem 'paperclip', :source => 'http://gemcutter.org'


RAILS_ROOTに移動して、paperclipをインストールします

$ rake gems:install


例として、あるサービス(service)があって、そのサービスに画像(service_image)を3つ登録できるアプリを作ります。


モデルを作成します。

$ ruby script/generate rspec_scaffold service name:string
$ ruby script/generate rspec_scaffold service_image service_id:integer image_file_name:string image_content_type:string image_file_size:integer


モデルの関連付けを行います。
app/models/service.rb

class Service < ActiveRecord::Base
  has_many :images, :class_name => "ServiceImage"
  accepts_nested_attributes_for :images
end

app/models/service_image.rb

class ServiceImage < ActiveRecord::Base
  belongs_to :service, :class_name => "Serviece"
end


コントローラでは、サービス画像を3つ設定してあげます。
app/controllers/services_controller.rb

  # GET /services/ne
  # GET /services/new.xml
  def new
    @service = Service.new
    # この一行を追加しました。
    3.times { @service.images.build }

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @service }
    end
  end


ビューでは、accepts_nested_attributes_forで関連付けを行ったので、
fields_forを使ってserviceにservice_imagesをネストすることができます。
注意するところは、:htmlオプションをfields_forではなく、form_forの方に記述しないと、ファイルが送信されません。

app/views/service/new.html.erb

<h1>New service</h1>

<!-- form_forに:htmlオプションを書かないと駄目です!! -->
<% form_for(@service, :html =>{ :multipart => true }) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>

  <% f.fields_for :images do |image_form| %>
    <p>
      <%= image_form.label :image %><br />
      <%= image_form.file_field :image %>
    </p>
  <% end %>

  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', services_path %>


thoughtbot/paperclip · GitHubを参考に、ファイルアップロードする部分を先程のServiceImageクラスに追加します。
app/models/service_image.rb

class ServiceImage < ActiveRecord::Base
  belongs_to :service, :class_name => "Serviece"
 
  # 画像サイズは4種類作成するようにしました。
  STYLES = { :thumb => '100x100>', :small => '240x240>', :medium => '500x500>', :large => '1024x1024>' }

  # ファイルをS3にアップロードする設定
  has_attached_file :image,
    :storage => :s3,
    :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
    :path => "service-images/:style/:filename",
    :styles => STYLES
end


上記のs3.ymlを作成します。
config/s3.yml

# bucketを作成して(今回はsandboxにしました。) 
# access_key_id、secret_access_keyは自分のkeyを設定してください。
development:
  bucket: 'sandbox'
  access_key_id: 'XXXXXXXXXXXXXXXXXXX'
  secret_access_key: 'XXxXXXxxxXxxXXXXXxxxXXXXxXXXXXxXXXXxXXX'

test:
  bucket: 'sandbox'
  access_key_id: 'XXXXXXXXXXXXXXXXXXX'
  secret_access_key: 'XXxXXXxxxXxxXXXXXxxxXXXXxXXXXXxXXXXxXXX'

production:
  bucket: 'sandbox'
  access_key_id: 'XXXXXXXXXXXXXXXXXXX'
  secret_access_key: 'XXxXXXxxxXxxXXXXXxxxXXXXxXXXXXxXXXXxXXX'


実装はここまでです。


できたら、http://localhost:3000/services/newにアクセスして、
サービス名とそのサービス画像を3つ登録するフォームが表示されることを確認します。


表示されたら実際に画像を選んで「create」ボタンを押してみましょう。
S3にファイルがアップロードできるはずです!


f:id:t-taira:20100820015508p:image
f:id:t-taira:20100820015507p:image