Webエンジニア目指して#41

どうも特に無いマンです。

暇ではないんですが、仕事ないとなんか足りないですね〜
腹が減ったときの飯が美味いのと同じで、ある程度ストレスないと娯楽も楽しみが減りますね。フリマに断捨離以外はやり残したことなくなってきたんで学習時間の増やしどころかも

さてやっていきましょうProgateのRails VIIです

目標は画像の投稿機能実装

テーブルへカラムを追加する

migrationファイルのみ作成しデータベースへ反映させる

$rails g migration ファイル名

試しに作ってみたものの中身がこれ

class AddImageNameToUsers < ActiveRecord::Migration[6.1]
  def change
  end
end

今回は空だが、実は今まで使っていた$rails g modelを実行した場合はchangeメソッドの中身は自動生成されていた

カラムを追加したい場合は以下のように書く

class AddImageNameToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :テーブル名, :カラム名, :データ型
  end
end

次に$rails db:migrateを実行するとchangeメソッドが実行され、対象のテーブルにカラムが追加される

試しに実行してみた f:id:misokatsu_sand:20210327013504p:plain

比較画像:実行前 f:id:misokatsu_sand:20210327014039p:plain 比較画像:実行後 f:id:misokatsu_sand:20210327014057p:plain image_nameカラムが増えたので成功

画像とリンクさせる

テーブルに追加したカラム名の文字列と画像ファイル名をレコードごとに一致させ、後はhtmlで参照するだけ

データベース

既存のレコードはimage_nameカラムが空だったので追加しておく f:id:misokatsu_sand:20210331003003p:plain

画像ファイルの保存場所

画像ファイル名とimage_nameカラムの値を一致させる f:id:misokatsu_sand:20210331010104p:plain

html

imgタグの参照先に先程一致させた値を使ってパスを埋める railsを使っているときはimgタグは/publicフォルダから参照されるため、それに合わせて記述する

<img src="<%= "/user_images/#{@user.image_name}" %>">

結果

f:id:misokatsu_sand:20210331014546p:plain

画像の投稿フォーム

html

<%= form_tag("/users/#{@user.id}/update",{multipart:true}) do %>
  <p>ユーザー名</p>
  <input name="name" value="<%= @user.name %>">
  <p>e-mail</p>
  <input name="email" value="<%= @user.email %>">
  <p>プロフィール画像</p>
  <input type="file" name="image">
  <p>-</p>
  <input type="submit" value="変更">
<% end %>

inputタグのtype属性をfileにするとファイルを選んで送信できる
また、name属性も指定しているため画像のデータが[:image]として送信される

ファイルの送信フォームがあるときは、form_tagの第2引数に{multipart:true}を入れる必要がある

見た目はこんな感じ

f:id:misokatsu_sand:20210401033819p:plain

画像を受け取り保存する

if params[:image]
  @user.image_name="#{@user.id}.jpg"
  image=params[:image]
  File.binwrite("puclic/user_images/#{@user.image_name}","image.read")
end

まずif params[:image]でファイルが選択されている場合のみの処理とし、
@user.image_name="#{@user.id}.jpg"でデータベースへファイル名を登録
image=params[:image]でファイルを受け取り、
File.binwrite("puclic/user_images/#{@user.image_name}",image.read)
指定ディレクトリへファイルを作成する。
画像データを受け取りファイル作成する場合は受け取ったハッシュに対してreadメソッドというものを使う

いやそもそもFile.binwriteってなんやねん、となるので説明

File.write("ファイル名のパス","ファイルの中身")

このようにFileクラスというものがあり、writeメソッドを使うことで指定のディレクトリへファイルを作成できる。
(パスはアプリケーションのルートディレクトリから参照するので注意)

File.write("public/test.txt","aiueo") を実行した場合は、/public/test.txtというファイルが作成され、その中身がaiueo、ということになる

File.binwriteはその中身が2進数のバージョンであり、readメソッドを使って受け取った画像ファイルを2進数のデータに変換してファイルを作成している。

失敗談だがimage.readは変数.メソッドなので"image.read"と書かないように注意(ファイル生成がうまく出来ていなかった)

結果

f:id:misokatsu_sand:20210401051226g:plain

これ、簡易的にtwitter作れるんじゃね・・・?

ってなわけでRails VIIはおわりです ではでは