Ruby
carrierwave
Rails4

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

More than 3 years have passed since last update.

概要

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

実装手順

ライブラリを準備する

Gemfileに以下の行を追加

gem 'carrierwave'

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

bundle install

モデルを準備する

carrierwaveのuploaderを生成する

rails generate uploader UploadFile

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

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

rails generate model UploadFile name:string file:string

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

rake db:migrate

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

/app/models/upload_file.rb
class UploadFile < ActiveRecord::Base
+  mount_uploader :file, UploadFileUploader
end

これでモデルに関する部分は完成。

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

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

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

rails generate controller uploader index form upload download

フォームを用意する

/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を受け取るように手直しする。

/config/routes.rb
+  post 'uploader/upload'
-  get 'uploader/upload'

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

/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

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

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

/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を使う
uploderのcurrent_pathを指定してダウンロードできるようにしている。

/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を使って見てみると、
モデルの中がどんなオブジェクトになっているのか確認できる。

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={}>

参考文献

ライセンス

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