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

どうも運動不足マンです。 出勤や構内を歩くのってかなり運動になっていたんだなあと感じてます。

さあ毎日やっていることが固定なのでネタが特にありません、技術的な話に参りましょう

rubyの課題は終わらせました。全て一発合格であまりにもさらっといって逆に不安です

というわけでrails編です。progateである程度はやったので思い出し+追加ですね

partial

htmlの共通パーツを作っておいて使い回せる
以下のようなやり方でできるが、viewsディレクトリにsharedフォルダを作りそこにpertialを格納するのが一般らしい

views/shared/_partial.html.erb

<p>partial</p>

views/main.html.erb

<%= render "shared/partial" %>

指定ファイルの.html.erbは省略でOK

sqliteのコマンド

$.tables 作成済テーブルの確認
$.schema テーブル名 テーブルの定義確認
ctrl+z .quitコマンドの代わり

CRUD処理の記述省略

こう書くと対象コントローラーに省略実装できる(actionは手動で記述が必要)

Rails.application.routes.draw do 
      resources :コントローラー名
end

さらに、メソッドでroute指定する際に以下のような例で指定できるようになる

 <%= link_to "ユーザー情報一覧", :users  %>

各アクションによって割り当てられるハッシュが違い、またupdateやdestroyなどのアクションはhttpメソッドを指定する必要があるためその都度確認したい

routing定義の確認

resourcesのように省略記述した際はroutes.rbでは詳細を確認できないため、
$rails routesCUIから確認する

なにやら色々出てくるので見たいところだけ抜粋 f:id:misokatsu_sand:20210907133315p:plain

form_forメソッド

progateではform_tagメソッドで下記のように記述しデータの受け渡し、データベースとのやりとりをしていた

<%= 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 %>

form_forを使えば、以下のように書けばその次のようにhtml変換される
(@users = User.all)

<%= form_for @user do |f| %>
  <%= f.text_field :name %>
<% end %>

<input type="text" name="user[name]" id="user_name">

paramsメソッド

今まではparams[:id]のようにform_tagメソッド内のname属性から拾った情報を使っていたが、form_forメソッドの場合は下記のように記述できる

@user = User.new(params.require(:user).permit(:name, :email))

paramsメソッドにはrequireメソッドとpermitメソッドがチェーンでき、
requireで対象テーブルのインスタンスを指定→permitで編集できるキーの指定をする。

これによって指定したオブジェクトでなければエラーを吐くため、意図しないキーの編集を防ぐことができるためストロングパラメータと呼ぶらしい

form_forめっちゃ便利...

created_atなどの時間情報を日本時間に変える

1.config/application.rbを開くとモジュールの中に入ったクラスが1つある
そこに下記の通り書いてある見本がある

# config.time_zone = "Central Time (US & Canada)"

これのコメントアウトを外してconfig.time_zone = 'Tokyo'に書き換える

2.config/initializersディレクトリにtime_formats.rbを作成し、以下のように書く

Time::DATE_FORMATS[:datetime_jp] = '%Y年 %m月%d日'

3.view中の時間を表示するオブジェクトに.to_s(:datetime_jp)をつける

<%= user.updated_at.to_s(:datetime_jp) %>
<%= user.created_at.to_s(:datetime_jp) %>

4.サーバーを再起動する
config/initializerはサーバー起動時に参照されるそう

結果 f:id:misokatsu_sand:20210910112720p:plain

updateメソッド

レコードに対して値の更新をするメソッド
これにもストロングパラメータを渡すのが良いらしい

@user.update(params.require(:user).permit(:name, :email))

data-confirm

link_toメソッドなどの引数にdata: { confirm: "メッセージ" }のように使うとポップアップアラートを表示させられる 下の例のようにdestroy処理などの不可逆処理の警告に使う

<%= link_to "削除", user, method: :delete, data: { confirm: "本当に削除しますか?" } %>

ちなみにこれは参照と同じリンク先になっているが、httpメソッドを指定することでdestroyアクションを呼び出すことになっている

モデルの関連付け(一対多)

railsではアソシエーションというらしい 例えばuserモデルにpostモデルを関連付けるなら、userに対し多数のpostを持つことになり、postに対し多数のuserは紐付かない。その場合は次のように書く

user.rb

class User < ApplicationRecord
  has_many :posts
end

post.rb

class Post < ApplicationRecord
  belongs_to :user
end

これを行うことで、あるuserのpostを全て表示したい場合は以前は以下のように書いていたが

@posts = Post.where(user_id: @user.id)

関連付けによって以下のように書けるようになる

@posts = @user.posts 

postのuserは以下のように書けるようになる

<%= @post.user.name %>

モデルの関連付け(多対多)

多対多の例は、postに対しuserのfavが追加されるパターン

favがあると1つのpostに対してのuserが一意に決まらないため、2つのテーブルだとfav用のカラムが半無限に増えてしまう(このpostにはこのユーザーがfavしました、のようなカラム)

このような多対多の場合はfavテーブルを作って中間テーブルにする。

下記が例

user.rb

class User < ApplicationRecord
  has_many :posts
  has_many :posts, through: fav
end

post.rb

class Post < ApplicationRecord
  belongs_to :user
  has_many :user, through: fav
end

fav.rb

class Fav < ApplicationRecord
  belongs_to :user
  belongs_to :post
end

has_many :favでも書けるが、例のようにthroughを使った書き方をするとpost<=>user間のダイレクトアクセスが可能となる

hidden_field

扱いたいが表示はしたくないパラメータがある場合に使える
下の例の場合は以前やったsession変数でもよさそう

<%= f.hidden_field :user_id, value: @user.id %>

renderメソッドで変数を渡す

以下のようにすると変数smpがtestパーシャルで使えるようになる

<%= render "shared/test", smp: @user %>

バリデーションなどのrailsメッセージを日本語化する

rails-i18nというgemで実装できる。 i18nはInternationalizationの略で、国際化の意味らしい

まずはgemfileに記述しbundle installする

gem 'rails-i18n'

config/application.rbに以下の記述をする

config.i18n.default_locale = :ja

これでエラー文が日本語化される f:id:misokatsu_sand:20210921153216p:plain

このNameやEmailなどのキーを日本語で表示するには、yamlという構造定義ファイルで定義する必要がある

config/localesディレクトリにja.ymlを作成し以下のように書く

ja:
  activerecord:
        models:
          user: ユーザー
        attributes:
          user:
            name: 名前
            email: メールアドレス
            age: 年齢
            introduction: 一言紹介

これでエラー文が日本語になった f:id:misokatsu_sand:20210921165229p:plain

この辺で区切ります。ではでは