Railsのあれこれ その5
既存のモデル(テーブル)にカラムを追加する
既存のテーブルに追加でカラムを追加します。 結構複雑です。
まず、ターミナルで
rails g migration add_image_name
このように、カラムを追加するためのマイグレーションファイルを追加します。 「add_image_name」というのがマイグレーションファイルの名前になります。 ここは任意でOK。
アプリ名>db>migrate の中に、
日付け_add_image_name
というファイルが追加されているはずなので、そこを編集します。
class Change < ActiveRecord::Migration[5.0] def change add_column :users, :image_name, :string end end
この場合は usersテーブルにimage_nameという文字列のカラムを追加します。
マイグレーションファイルのchangeメソッドの中に
def change add_column :テーブル名, :カラム名, :データ型 end
このように記述します。テーブル名はモデル名の複数形になるので注意しましょう。(例:Userモデルの場合、users)
そうしたら、 ターミナルで
rails db:migrate
と打ちます。 これで、さきほどマイグレーションファイルに書いた変更がデータベースに反映されます。 確認してみましょう。
image_name
という文字列のカラムが追加されているはずです。
画像を参照するときの書き方
これが結構地味に頭がこんがらがります。
<img src="<%= "/user_images/#{画像名}" %>">
このようにします。
画像名の変数が image_name だとすると
<img src="<%= "/user_images/#{image_name}" %>">
こうなる訳ですね。 外側の""ダブルクオーテーション2つは、ただのマークアップのための表示、 そして内側のダブルクオーテーション2つはrubyの変数を式として評価するためのものです。
<%= "#{image_name}" %>
このようになっていた場合、rubyでは image_nameを変数として出力する訳です。 今回は
<img src="<%= "/user_images/#{image_name}" %>">
となっているので、
<%= "/user_images/#{image_name}" %>
までがrubyの式として表示させたい部分ですね。 いちばん外側にあるダブルクオーテーションは「マークアップのためのダブルクオーテーションマーク」ということです。 いや~ややこしい。
この「rubyの式の展開」についてはよく覚えて、慣れておきましょう。
画像を登録する
画像です。画像の登録。
コントローラーのcreateでは、
def create @user = User.new(name: params[:name], email: params[:email], image_name: "default_user.jpg") if @user.save flash[:notice] = "ユーザー登録が完了しました" redirect_to("/users/#{@user.id}") else render("users/new") end end
のようにして、まずUser.newをするときに、画像にデフォルトの画像ファイルを設定します。
その次に、画像を編集する場合です。
edit.html.erbに
<p>画像</p> <input name="image" type="file">
を追加します。
input属性のnameはimageという名前にしましょう。 そして、ポイントはファイルタイプを「file」とすることです。 これで画像ファイルが取得できます。
ただし、送信フォームに
<%= form_tag("/users/#{@user.id}/update", {multipart: true}) do %>
のようにして、フォームに
{multipart: true}
をつけます。これをすることにより、ファイルが送信出来るようになります。
そして、コントローラーのupdateアクションでは「画像がある場合に登録する」 という処理を記載します。
ファイルがあるときのみ実行するif文を書きます。
def update @user = User.find_by(id: params[:id]) @user.name = params[:name] @user.email = params[:email] if params[:image] @user.image_name = "#{@user.id}.jpg" image = params[:image] File.binwrite("public/user_images/#{@user.image_name}", image.read) end if @user.save flash[:notice] = "ユーザー情報を編集しました" redirect_to("/users/#{@user.id}") else render("users/edit") end end
このようになります。
if params[:image]
の部分で、「画像がもしある場合」 として処理を実行しています。
ファイルを保存するには
File.binwrite("public/user_images/#{画像名}", 画像データ.read)
というようにして画像ファイルを入れる場所と、画像データを指定します。
上記では
@user.image_name = "#{@user.id}.jpg" image = params[:image] File.binwrite("public/user_images/#{@user.image_name}", image.read)
の部分です。 public/user_images/ というフォルダに、画像を書き込んでいることが分かります。 この場合のファイル名はユーザーIDを使っています。
かなりややこしいですね。 binwriteメソッドとreadメソッドについても調べておきましょう。