2018-05-05追記: Rails 5.0.7で試したけど、この内容で特に問題ないっぽいです。

タネマキの常連さんの松本さんにCarrierWaveてのを教えてもらいました。最近のファイルアップロードはこれがイケてるらしい。

使い方は僕の方で調べたものなんで、もしかしたらおかしいかもしれない。

概要

何それ

これこれ。

めんどい

そんなあなたのためにシェルスクリプトをご用意致しました。

sedまじ便利。

環境

  • ruby 2.0.0p247
  • Rails 4.0.0

準備

アプリ作成

rails new uploader
cd uploader

CarrierWave導入

  • Gemfile
gem 'carrierwave'
bundle

投稿モデル作成

rails g scaffold post name:string comment:text
rake db:migrate

アップロード機能を追加

rails g uploader Image
rails g migration add_images_to_posts image:string
rake db:migrate
  • app/models/post.rb
class Post < ActiveRecord::Base
  mount_uploader :image, ImageUploader
end
  • app/views/posts/_form.html.erb
  <div class=field>
    <%= f.label :image %><br>
    <%= f.file_field :image %>
  </div>
  • app/views/posts/show.html.erb
<p><%= image_tag @post.image_url %></p>
  • app/controllers/posts_controller.rb
    def post_params
      params.require(:post).permit(:name, :comment, :image)
    end

出来上がり

投稿画面。

閲覧画面。
画像はフルサイズ。

RMagickでサイズ変更したりとか

ImageMagickとかのRuby用インターフェイス、だそうです。ImageMagickは超有名な画像処理ソフト。(アプリじゃない。)

動的に変更して出力するのではなく、アップロード時に規定サイズに拡縮した画像を生成する流れ。

インストール

手元のDebianの場合。他のディストリ、OSは各自調べてください。

aptitude install libmagick9-dev
gem install rmagick --no-ri --no-rdoc

RMagick導入

  • Gemfile
gem 'rmagick'
bundle

アップロード時にリサイズしてもらう

  • app/uploaders/image_uploader.rb
  # Include RMagick or MiniMagick support:
  include CarrierWave::RMagick
  # include CarrierWave::MiniMagick
  • app/uploaders/image_uploader.rb
  # Create different versions of your uploaded files:
  version :thumb do
    process :resize_to_fit => [50, 50]
  end

s/:scale/:resize_to_fit/ を忘れないように。

resize_to_fitresize_to_limitの違いはよくわからない。

リサイズされた画像を表示

  • app/views/posts/index.html.erb
    <tr>
      <th>Name</th>
      <th>Comment</th>
      <th>Thumbnail</th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
      <tr>
        <td><%= post.name %></td>
        <td><%= post.comment %></td>
        <td><%= image_tag post.image_url(:thumb) %></td>
        <td><%= link_to 'Show', post %></td>
        <td><%= link_to 'Edit', edit_post_path(post) %></td>
        <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>

出来たね

一覧画面。
画像は小さい。

おしまい

最初rails new ImageUploaderとやっていたんだけど、変なエラーが出て困りました。uploaderのImageUploaderと被ったのが良くなかったみたい。

発展

画像ならサムネイル表示、そうでないならただのリンクで表示、みたいにするとよりアップローダーっぽい気がする。

Content Typeを得るにはアップロード時に取得しておく必要があるらしい:

あとCarrierWaveのドキュメントだとUser.avatarという風にしている。この場合は、ファイルがあれば更新、なければそのまま、削除チェックボックスがオンなら削除してデフォルト画像を表示……とかするべきなんだろう。また大変そうだ。

参考

追記

uninitialized constantと言われたら

rails s を再起動したら直りました。