Herokuで作るFacebookアプリ

第11回 Herokuでファイルアップロードを実装しよう

この記事を読むのに必要な時間:およそ 2 分

はじめに

前回は,Herokuのコマンドの拡張pluginについて解説しました。ちょっとマニアックだったかと思いますが,Herokuのオープンであるというビジョンが見える非常に面白い仕組みだと思います。今回は,マンガ共有サービスの機能を追加したいと思います。Webサービスでは必須の機能のファイルアップロードの仕組みをHerokuを利用する場合どのように実現するかを紹介します。

Herokuでのファイルの扱い

Heroku上では,ファイルをサーバ上に保存するということができません。これは,以下の理由からそのようになっていると思います。

  • Webサーバのインスタンスがどのサーバで動くかが特定できない
  • 複数インスタンスが動いた場合に,同じファイルシステムを共有できない

Herokuでは,マルチインスタンスのプラットホームであるためこのような課題が出てきます。この問題をおそらく解決することはできるかもしれませんが,Herokuではアクセスを不可にしています。ファイルシステムを扱うことは他のサービスと組み合わせて利用することで代替が可能です。そうすることで,Herokuはシンプルな構成を維持できるのだと思います。

Herokuでファイルアップロードを実現するためにはファイルをサーバのファイルシステムに保存するのではなく,別の場所に保存するようにしないといけません。一般的にHerokuでファイルを保存する際に利用されるのは,Amazon S3ではないでしょうか?

Amazon S3は,Amazonが提供しているファイルストレージサービスです。S3を利用するには,Amazon Web Serviceの登録が必要です。非常に堅牢で安価なので,多くのサービスがAmazon S3を利用してファイルの保存や配信を行っています。

今回は,そのAmazon S3を利用してファイルアップロードを実現する方法を紹介します。マンガ共有サービスとしては,マンガに自分の好きな写真を載せられるという機能とします。こちらにアクセスして動作を試してみてください。マンガの編集画面からファイルアップロードができるようになっています。

carrierwaveでファイルアップロード

Ruby on Rails でファイルアップロードを実現するために,いくつかのgemがあります。代表的なものとして,以下の3つが上がります。

今回はこの中でも一番新しく出てきたcarrierwaveというgemを利用してファイルアップロードを実装します。まずは,ファイルをアップロードする部分を標準のローカルファイルシステムに保存する形で機能を実現します。

Gemfileに以下の行を追加します

gem "carrierwave"

gemを追加したので,bundlerを利用してgemをインストールします。

$ bundle

まずは,carrierwaveを利用するためにファイルをgenerateします。以下のコマンドを発行すると,ファイルアップロード用のクラスが生成されます。

$ rails g uploader image

既存のmangaクラスに画像を追加する形にするために,mangasテーブルにimageカラムを追加します。

$ rails g migration add_image_to_mangas image:string

マイグレーションファイルが生成されるので,マイグレーションを実行します。

$ rake db:migrate

次に,mangaクラス(app/models/manga.rb)にアップロードファイルをひもづけるためのコードを追加します。

attr_accessible :title, :author, :amazon_image_url, :image
mount_uploader :image, ImageUploader

attr_accessibleに,:imageを追加して,フォームから登録が可能にします。mount_uploaderメソッドを実行してクラスにアップロードファイルを紐付けます。

最後に,編集のための入力フォーム(app/views/mangas/_form.html.haml)を修正します。

= form_for @manga, :html => {:multipart => true} do |f|
  = f.error_messages
  %p
    = f.label :title
    %br
    = f.text_field :title
  %p
    = f.label :author
    %br
    = f.text_field :author
  %p
    = f.file_field :image
  %p
    = f.submit

form_forメソッドに :html => {:multipart => ture} の引数を追加してformタグをマルチパートにしてファイルアップロード可能にします。f.file_field :imageを追加してファイルアップロードの入力ボックスを追加します。

以上の変更点は,こちらのコミットになっています。carrierwaveを用いることで非常に簡単にファイルアップロードが実現できました。

著者プロフィール

松村章弘(まつむらあきひろ,ハンドルネーム:mat_aki)

SonicGarden プログラマー。

1984年生まれ。社会人1年目からRuby on Railsのみで開発を続け現在4年目。Webサービスの企画・運営・プログラミングまですべてをこなす。世界で利用されるWebサービスを創ることを目標にしている。現在は youRoom の開発を行っている。

mat_akiの日記:http://d.hatena.ne.jp/mat_aki/

Twitter:http://twitter.com/mat_aki

コメント

コメントの記入