読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

RailsのファイルをアップロードするgemのCarrierWaveのインストール方法

Rails gem ファイルアップロード

CarrierWaveとは

f:id:nipe880324:20141015002041j:plain:w240

CarrierWaveとは有名なファイルアップロード用のgemです。他にはPaperclipというものもあります。
この2つがRuby/Railsでのファイルアップロードgemとしてトップ2を争っています。

これらの違いは、

  • Paperclipは機能がシンプルで使いやすい
  • CarrierWaveは機能がいろいろあり、応用が聞きやすい

です。

完成イメージ

新規/編集画面で画像をアップロードをし、次のように詳細画面で表示することができます。
また、チェックボックスをつけて、削除することも可能です。
f:id:nipe880324:20141015000556p:plain:w320


実施環境

  • Mac OS X 10.9
  • Ruby 2.0
  • Rails 4.1
  • CarrierWave 0.10.0

目次

  1. Railsプロジェクトの作成
  2. CarrierWaveのインストールと導入
  3. CarrierWaveの良く使うメソッド


Railsプロジェクトの作成

まず Railsプロジェクトを作成します。

rails new carrierwave_test

そして Scaffoldで簡単なProductクラスを作ります。

cd carrierwave_test
rails g scaffold Product name:string price:integer

では DBマイグレートをして、ローカル環境で動かしてみましょう。

rake db:migrate
rails s

以下のような画面ができるはずです。

f:id:nipe880324:20141015000549p:plain:w480



CarrierWaveのインストールと導入

Gemのインストール

では、CarrierWaveのインストールをプロジェクトに導入します。

# Gemfile
...
gem "carrierwave"

gemをインストールします。

bundle install

アップローダーの生成

CarrierWaveのジェネレーターでアップローダーを作成します

rails g uploader Image
      create  app/uploaders/image_uploader.rb

作成されたファイルのimage_uploader.rbの中をのぞいてみると、ファイルの保存方法(デフォルトはファイル)、保存パス、ファイルのサイズ、拡張子やファイル名の変換などが変更できることがわかると思います。

CarrierWaveはActiveRecordやMongoId、DataMapperなどのORMと連携することができます。
今回は、RailsのデフォルトでもあるActiveRecordを使って、アップロードしたファイルの情報を保存します。

Modelに画像情報保持用のカラムの追加

まずは、Stringカラムをモデルに追加するために、Productモデルにマイグレーションファイルを作成し、マイグレートをします。

rails g migration add_image_to_product image:string
rake db:migrate

その後、モデルファイルを開き、アップローダーへのマウントする記述を追加します。

# app/models/product.rb
class Product < ActiveRecord::Base
  mount_uploader :image, ImageUploader
end

画像の追加/編集/表示/削除処理の追加

商品の新規/編集フォームに画像アップロードの入力フィールドを追加します。
hidden属性でimage_cacheを指定しましたが、これは、画像を指定したけれども、バリデーションエラーなどにより保存が失敗した場合の画面再表示時などに、画像情報をキャッシュしておくための領域です。

# app/views/products/_form.html.erb

<%= form_for(@product) do |f| %>
  <% if @product.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>

      <ul>
      <% @product.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :price %><br>
    <%= f.number_field :price %>
  </div>
  <!-- 追加箇所 開始 -->
  <div class="field">
    <% if @product.image? %>
      <div class="thumbnail">
        <%= image_tag @product.image.url %>
      </div>
    <% end %><br>
    <%= f.label :image %><br>
    <%= f.file_field :image %>
    <%= f.hidden_field :image_cache %>
  </div>
  <div class="field">
    <!-- 既存レコード(DBに保存されている)かつ、画像が存在する場合 -->
    <% if @product.persisted? && @product.image? %>
      <label>
        <%= f.check_box :remove_image %>
        画像を削除
      </label>
    <% end %>
  </div>
  <!-- 追加箇所 終了 -->
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>


コントローラーにファイルの属性を更新できるようにするために、StrongParametersの箇所を修正します。

# app/controllers/products_controller.rb

...
    # Never trust parameters from the scary internet, only allow the white list through.
    def product_params
      params.require(:product).permit(:name, :price, :image, :image_cache, :remove_image)
    end

end

そして、画像がアップロードされたら、詳細画面で表示するようにします。

# app/views/products/show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @product.name %>
</p>

<p>
  <strong>Price:</strong>
  <%= @product.price %>
</p>

<!-- 追加箇所 開始 -->
<p>
  <strong>Image:</strong>
  <% if @product.image? %>
    <div class="thumbnail">
      <%= image_tag @product.image.url %>
    </div>
  <% end %>
</p>
<!-- 追加箇所 終了 -->

<%= link_to 'Edit', edit_product_path(@product) %> |
<%= link_to 'Back', products_path %>


では、サーバーを起動して画像を登録してみましょう。
新規画面から画像を選択し、登録を押すと次のように画像が表示されます。
f:id:nipe880324:20141015000556p:plain:w320

また、このアップロードされたファイルはpublic/uploads/products配下に保存されています。
f:id:nipe880324:20141015000604p:plain:w230


CarrierWaveの良く使うメソッド

アップローダーをincludeしたモデル次のようなメソッドを使えます

# モデルの作成
product       = Product.new

# 画像ファイルの設定
product.image = params[:image]         # paramsから設定
product.image = File.open('somewhere') # Fileオブジェクトを設定

# 保存
product.save!

# アップローダーの対するメソッド
product.image.url          # => '/url/to/file.png'
product.image.current_path # => 'path/to/file.png'
prodcut.image.identifier   # => 'file.png'
product.image?   # => imageがあるかを true or false で返す

今回はCarrierWaveの基礎的な内容を記載しましたが、比較的簡単に画像のCRUDをActiveRecordのモデルに追加することができました。
次は、より深くCarrierWaveを使うためのカスタマイズ方法を説明します。

間違っている箇所のご指摘、良く分からないといった質問などありましたら、お気軽に以下のコメント欄に記載ください。直に返します。