今日やったこと16
13.4 マイクロポストの画像投稿
投稿した画像を扱ったり、その画像をMicropostモデルと関連付けするために、CarrierWaveという画像アップローダーを使う。まずはcarrierwave gemをGemfileに追加する。画像をリサイズしたり、本番環境で画像をアップロードするために、mini_magick gemとfog gemsも追加する。
source 'https://rubygems.org' gem 'rails', '5.1.4' gem 'bcrypt', '3.1.11' gem 'faker', '1.7.3' gem 'carrierwave', '1.2.2' #追加 gem 'mini_magick', '4.7.0' #追加 gem 'will_paginate', '3.1.5' gem 'bootstrap-will_paginate', '1.0.0' . . . group :production do gem 'pg', '0.20.0' gem 'fog', '1.42' #追加 end . . .
$ bundle install
CarrierWaveを導入すると、Railsのジェネレーターで画像アップローダーが生成できるようになる。
$ rails generate uploader Picture
関連付けされる属性には画像のファイル名が格納されるため、String型にしてpicture属性をMicropostモデルに追加する。
$ rails generate migration add_picture_to_microposts picture:string $ rails db:migrate
CarrierWaveに画像と関連付けたモデルを伝えるためには、mount_uploaderというメソッドを使い、引数に属性名のシンボルと生成されたアップローダーのクラス名を取る。これをMicropostモデルに追加する。
app/models/micropost.rb class Micropost < ApplicationRecord belongs_to :user default_scope -> { order(created_at: :desc) } mount_uploader :picture, PictureUploader #追加 validates :user_id, presence: true validates :content, presence: true, length: { maximum: 140 } end
Homeページにアップローダーを追加するために、マイクロポストのフォームにfile_fieldタグを追加。
app/views/shared/_micropost_form.html.erb <%= form_for(@micropost) do |f| %> <%= render 'shared/error_messages', object: f.object %> <div class="field"> <%= f.text_area :content, placeholder: "Compose new micropost..." %> </div> <%= f.submit "Post", class: "btn btn-primary" %> <span class="picture"> <%= f.file_field :picture %> <!-- file_fieldタグを追加 --> </span> <% end %>
micropost_paramsメソッドにpicture属性を追加する。
app/controllers/microposts_controller.rb class MicropostsController < ApplicationController before_action :logged_in_user, only: [:create, :destroy] before_action :correct_user, only: :destroy . . . private def micropost_params params.require(:micropost).permit(:content, :picture) # picture属性を追加 end def correct_user @micropost = current_user.microposts.find_by(id: params[:id]) redirect_to root_url if @micropost.nil? end end
Micropostパーシャルのimage_tagヘルパーでアップロードされた画像を描画する。
app/views/microposts/_micropost.html.erb <li id="micropost-<%= micropost.id %>"> <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %> <span class="user"><%= link_to micropost.user.name, micropost.user %></span> <span class="content"> <%= micropost.content %> <!-- image_tagヘルパーで画像を描画 --> <%= image_tag micropost.picture.url if micropost.picture? %> </span> <span class="timestamp"> Posted <%= time_ago_in_words(micropost.created_at) %> ago. <% if current_user?(micropost.user) %> <%= link_to "delete", micropost, method: :delete, data: { confirm: "You sure?" } %> <% end %> </span> </li>