LoginSignup
7
15

More than 3 years have passed since last update.

【Rails】CarrierWaveとrmagickでプロフィール画像を設定できるようにする

Posted at

CarrierWaveで画像のアップロード機能を実装する

今回はユーザーテーブルにプロフィール画像を設定できるようにします。

1. モデルに画像アップロード用のカラムを設定する

userモデルに画像をアップロードするためのimageカラムを追加します。

$ rails g migration add_image_column_to_users image:string

マイグレーションファイルの内容を適用します。

$ rails db:migration

もしすでにデータベース内にimageカラムを持っていないユーザーデータが存在しているなら、データベースの中身を一度リセットする必要があります。

$ rake db:migrate:reset

2. Gemfileにcarrierwaveを追加してbundle installを実行

Gemfile
gem 'carrierwave'
$ bundle install

サーバーの再起動も忘れないように、このタイミングで。(基本いつでも大丈夫)

rails s

3. rails g uploader imageで画像のアップローダークラスを作成

$ rails g uploader image

これで画像をアップロードできるようになります。

4. アップローダを実装したいクラスに以下のコードを追加

/app/models/user.rb
mount_uploader :image, ImageUploader

5. Strong Parameterにimageカラムを追加

/app/controllers/users_controller.rb
def user_params
  params.require(:user).permit(:name, :email, :image)
end

これで画像をアップロードする準備が整いました、あとはviewを記述するだけです。

6. 画像の表示・投稿するためのviewを記述

画像表示するためのview

/app/views/users/show.html.erb
<% if @user.image? %>                                                              
  <%= image_tag @user.image.url %>
<% end %>

画像を投稿するためのview

/app/views/users/new.html.erb
<%= f.label :image %>
<%= f.file_field :image %>

これで画像の表示・投稿機能が完成しました!
アップロードした画像はpublicフォルダ内に格納されていました。しかしこのままではアップロードしたときの画像名・大きさでフォルダ内に保存されるので、画像の加工を行うgemのrmagickを利用します。

rmagicで画像の加工を行う

rmagickのgemをインストールするにはimageMagickがインストールされていないといけないそうです。

imageMagickがインストールされているかは以下のコマンドで確認できます。

$ convert -version

もしインストールされていなかったらimageMagickをインストールしてください。Macの場合はbrewを使えばインストールできるそうです。

$ brew install imagemagick@6

1. Gemfileにrmagickを追加してbundle installを実行します

Gemfile
gem 'rmagick'                                                                      
$ bundle install

サーバーの再起動も忘れないでね

2. image_uploader.rbで設定を記述する

画像をどのような形式に加工するかは、/app/uploaders/image_uploader.rbで設定できます。

デフォルトでは以下のようになっています、このファイルを編集していきます。

/app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url(*args)
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  # Process files as they are uploaded:
  # process scale: [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:
  # version :thumb do
  #   process resize_to_fit: [50, 50]
  # end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  # def extension_whitelist
  #   %w(jpg jpeg gif png)
  # end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end
end

変更を加えたファイルはこのようになりました。

/app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base  

  # リサイズしたり画像形式を変更するのに必要
  include CarrierWave::RMagick

  # 画像の上限を640x480にする
  process :resize_to_limit => [640, 480]

  # 保存形式をJPGにする
  process :convert => 'jpg'

  # サムネイルを生成する設定
  version :thumb do
    process :resize_to_limit => [300, 300]
  end

  version :thumb100 do
    process :resize_to_limit => [100, 100]
  end

  version :thumb30 do
    process :resize_to_limit => [30, 30]
  end

  # jpg,jpeg,gif,pngしか受け付けない
  def extension_white_list
    %w(jpg jpeg gif png)
  end

  # 拡張子が同じでないとGIFをJPGとかにコンバートできないので、ファイル名を変更
  def filename
    super.chomp(File.extname(super)) + '.jpg' if original_filename.present?
  end

  # ファイル名を日付にするとタイミングのせいでサムネイル名がずれる
  #ファイル名はランダムで一意になる
  def filename
    "#{secure_token}.#{file.extension}" if original_filename.present?
  end

  protected
  def secure_token
    var = :"@#{mounted_as}_secure_token"
    model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
  end

end

これで完了です!

参考

https://pg-happy.jp/carrierwave-rmagic-uploader.html
https://nyoken.com/rails-carrierwave

image_uploader.rbについて
http://www.workabroad.jp/tech/1118
https://qiita.com/tackey/items/ba68ca8489500b7cb739

7
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
15