Railsでアップローダを作って覚えるCarrierwaveのチュートリアル

概要
====

Carrierwaveのサンプルコードは、画像の処理とscaffoldが多いので自力でアップローダを作ってみるチュートリアルを作りました。
最低限Railsが動く状態からスタートすることを想定しています。

実装手順
========

ライブラリを準備する
--------------------

Gemfileに以下の行を追加

``` {.ruby}
gem 'carrierwave'
```

以下のコマンドでインストール

``` {.ruby}
bundle install
```

モデルを準備する
----------------

carrierwaveのuploaderを生成する

``` {.bash}
rails generate uploader UploadFile
```

uploaderの細かい設定を行いたい場合には、 ```/app/uploaders/upload_file_uploader.rb``` を変更する。


コマンドでファイルを扱うためのモデルを作成

``` {.bash}
rails generate model UploadFile name:string file:string
```

以下のコマンドでDBを生成

``` {.bash}
rake db:migrate
```

生成したモデルに、mount_uploaderを追加する。
このときに追加するのは、```rails generate uploader```で生成したUploadFileなので、
末尾に```Uploader```を追加して、```UploadFileUploader```になる。

``` {.diff:/app/models/upload_file.rb}
class UploadFile < ActiveRecord::Base
+  mount_uploader :file, UploadFileUploader
end
```
これでモデルに関する部分は完成。

UIからアップロードできるようにする
----------------------------------

アップロードするためのWebの処理を作成する

後から使うdownloadやindexも同時に生成しておく

``` {.bash}
rails generate controller uploader index form upload download
```

フォームを用意する

``` {.erb:/app/views/uploader/form.html.erb}
    <% @upload = UploadFile.new %>
    <%= form_for @upload, :url => {:action => :upload} do |f| %>
      <%= f.label :name, "name" %>
      <%= f.text_field :name %>
      <%= f.label :file %>
      <%= f.file_field :file %>
      <%= f.submit "Upload" %>
    <% end %>
```

コントローラの生成時に自動的に生成されたroutes.rbがPOSTを受け取るように手直しする。

``` {.diff:/config/routes.rb}
+  post 'uploader/upload'
-  get 'uploader/upload'
```

ファイルを保存してindexにリダイレクトする処理をコントローラに追加

``` {.ruby:/app/controllers/uploader_controller.rb}
  def upload
    @upload_file = UploadFile.new( params.require(:upload_file).permit(:name, :file) )
    @upload_file.save
    redirect_to action: 'index'
  end
```

アップロードしたファイル一覧を見れるようにする
----------------------------------------------

アップロードされたファイルの一覧を確認する。

``` {.erb:/app/views/uploader/index.html.erb}
    <%= link_to 'アップロードはこちら', action: "form" %>
    <ul>
      <% UploadFile.all.reverse_order.each do |upload| %>
        <li><%= link_to upload.name, action: "download", id: upload.id %>
      <% end %>
    </ul>
```
ダウンロードできるようにする
----------------------------

ダウンロードにはRailsのdownload用のメソッド[send_file](http://railsdoc.com/references/send_file)を使う
uploderのcurrent_pathを指定してダウンロードできるようにしている。

``` {.diff:/app/controllers/uploader_controller.rb}
  def download
+    @upload_file = UploadFile.find(params[:id].to_i)
+    filepath = @upload_file.file.current_path
+    stat = File::stat(filepath)
+    send_file(filepath, :filename => @upload_file.file.url.gsub(/.*\//,''), :length => stat.size)
  end
```

データを1つ以上アップロードした後にRails Consoleを使って見てみると、
モデルの中がどんなオブジェクトになっているのか確認できる。

``` {.ruby:rails console}
> UploadFile
#=> UploadFile(id: integer, name: string, file: string, created_at: datetime, updated_at: datetime)

> UploadFile.first.file.class
#=> UploadFileUploader

> ploadFile.first.file
#=> #<UploadFileUploader:0x007fb75c6fc3e8 @model=#<UploadFile id: 1, name: "hoge", file: "hoge.pdf", created_at: "2015-04-12 17:40:45", updated_at: "2015-04-12 17:40:45">, @mounted_as=:file, @storage=#<CarrierWave::Storage::File:0x007fb75c6fc118 @uploader=#<UploadFileUploader:0x007fb75c6fc3e8 ...>>, @file=#<CarrierWave::SanitizedFile:0x007fb75ba16ca0 @file="/Users/user_name/app_name/public/uploads/upload_file/file/1/hoge.pdf", @original_filename=nil, @content_type=nil>, @versions={}>
```

参考文献
========

-   [carrierwaveuploader/carrierwave](https://github.com/carrierwaveuploader/carrierwave)
-   [RailsのファイルをアップロードするgemのCarrierWaveのインストール方法 -
    Rails
    Webook](http://ruby-rails.hatenadiary.com/entry/20141015/1413300088)

ライセンス
========

こちらのコードはMITライセンスです。