【Rails】[アクション名].html.erbについて

# 記事概要
Ruby on Railsのビューについて、まとめる

# 前提
- Ruby on Railsでアプリケーションを作成している

# 基本情報
## ファイルパス
app/views/[コントローラー名]/[アクション名].html.erb

## 記載方法
### 文字情報

|コントローラーの情報|記述|説明|
|---|---|---|
|受け取らない|[HTML](https://qiita.com/likapantrip/items/5cd8625437aefe0614ef)要素||
|受け取る|`<%= Rubyコード %>`|RubyコードをHTMLに埋め込み、ブラウザに表示される|
|受け取る|`<% Rubyコード %>`|RubyコードをHTMLに埋め込めるが、ブラウザに表示されない|

### ID情報を含めたルーティング
ルーティングの`/:id`部分にテーブルのID情報を与えることで、任意のパスに移動できる

|パターン|説明|例|
|-|-|-|
|URIパターン|URIパターンの`/:id`部分に、`/#{レコード情報を格納した変数.id}`を記述|`"/tweets/#{tweet.id}"`|
|Prefix|Prefix_pathの後に、`(レコード情報を格納した変数.id)`を記述|`tweet_path(tweet.id)`|

### コメントアウト
```erb
<%# コメントアウト %>
```

## ヘルパーメソッド
ビューでHTMLタグを出現させたりテキストを加工するために使用するメソッドの総称

ヘルパーメソッドを使用する利点は、下記
- パスの指定やRubyの埋め込みなどの記述がシンプルになるため
- セキュリティ上の問題を解消するため

# まとめ(データ表示)
## 単一レコード情報の表示
表示するカラムを指定し、カラムの情報を表示する

```erb
<!-- インスタンス変数に格納されている単一レコード情報のカラムを表示 -->
<%= @インスタンス変数名.カラム名 %>

<!-- @postに格納されているレコードのcontentカラムを表示 -->
<%= @post.content %>
```

## 複数レコード情報の表示
繰り返し処理などを使用し、値を1つずつ表示する

[![Image from Gyazo](https://i.gyazo.com/84c2b332abeeedaff3f6eed4131bbdc1.png)](https://gyazo.com/84c2b332abeeedaff3f6eed4131bbdc1)

## eachメソッド
詳細は、[こちら](https://qiita.com/likapantrip/items/655e2c8fc2d4c02eb12e#eachメソッド)を参照

```erb
<!-- @postsに格納されているレコードのcontentカラムを順番に表示 -->
<% @posts.each do |p| %>
  <%= p.content %>
<% end %>
```

## user_signed_in?メソッド
詳細は、[こちら](https://qiita.com/likapantrip/items/655e2c8fc2d4c02eb12e#user_signed_inメソッド)を参照

```erb
<% if user_signed_in? %>
    <!-- ログインユーザーの場合 -->
    <%= link_to "ログアウト", destroy_user_session_path, data: { turbo_method: :delete } %>
<% else %>
    <!-- ログアウトユーザーの場合 -->
    <%= link_to "ログイン", new_user_session_path %>
    <%= link_to "新規登録", new_user_registration_path %>
<% end %>
```

## current_userメソッド
詳細は、[こちら](https://qiita.com/likapantrip/items/655e2c8fc2d4c02eb12e#current_userメソッド)を参照

```ruby
# ログインユーザーIDが必要なルーティング
"/users/#{current_user.id}"
```

## renderメソッド
[部分テンプレート](https://qiita.com/likapantrip/items/42de2051747158b59e6b)を呼び出す際に利用するメソッド
※コントローラーに同名のメソッドが存在するが、別物

### partialオプション
呼び出す部分テンプレート名を指定する

```erb
<!-- ビューファイルと同じフォルダにある_sample.html.erbを呼び出す -->
<%= render partial: "sample" %>

<!-- ビューファイルと異なるフォルダにあるapp/views/shared/_sample.html.erbを呼び出す -->
<%= render partial: "shared/sample" %>
```

### localsオプション
部分テンプレートで使用できる変数を指定する

```erb
<!-- 部分テンプレートにて、"hello!"という文字列の代入された変数postが使用できる -->
<%= render partial: "sample", locals: { post: "hello!" } %>
```

### collectionオプション
指定したインスタンス変数の中にある要素の数だけ、部分テンプレートを繰り返し呼び出すことができるオプション

```erb
<!-- @hogesには繰り返し表示させたい要素が複数入っている -->

<!-- collectionオプションを使用しない場合 -->
<% @hoges.each do |hoge|%>
  <%= render partial: 'hoge', locals: {hoge: hoge} %>
<% end %>

<!-- collectionオプションを使用する場合 -->
<!-- @hogesから取り出された1つ1つの要素は、部分テンプレートでhogeとして扱える -->
<%= render partial: 'hoge', collection: @hoges %>
```

## lメソッド
日付や時刻を表示するメソッド
国や地域によって時刻は異なるが、`l`メソッドを使えば指定した現地時間を表示できる

別途、[年月日と時刻の設定](https://qiita.com/likapantrip/items/2b43ea0432f8f457049d#年月日と時刻の設定)を行うことも可能

```erb
<!-- 投稿した時刻を出力する -->
<%= l tweet.created_at %>
```

## attached?メソッド
レコードにファイルが添付されているかどうかで、`true`か`false`を返すメソッド

```erb
<%= モデル.ファイル名.attached? %>

<!-- 画像が存在する場合のみimage_tagが読み込まれる -->
<%= image_tag message.image if message.image.attached? %>
```

## variantメソッド
Active Storageを導入している場合に、ファイルの表示サイズを指定できるメソッド

```erb
<!-- 幅x高さのxは、半角英数のx（エックス）を使用 -->
<%= モデル.ファイル名.variant(resize: '幅x高さ') %>
```

## collection_selectメソッド
モデルのデータと連携してセレクトボックスを表示できるメソッド

セレクトボックスのメニューに表示する項目を、テーブルやアクティブハッシュを用いて定義することができる

```erb
<%= form.collection_select(保存されるカラム名, オブジェクトの配列, カラムに保存される項目, 選択肢に表示されるカラム名, オプション, htmlオプション) %>
```

### 引数
各引数に対応する値と役割は以下。　※第1〜第4引数は必ず設定する

|引数|値|役割|
|-|-|-|
|第1引数<br>(保存されるカラム名)|:genre_id|保存先のカラム名|
|第2引数<br>(オブジェクトの配列)|Genre.all|配列データを指定|
|第3引数<br>(カラムに保存される項目)|id|表示する際に参照するDBのカラム名|
|第4引数<br>(選択肢に表示されるカラム名)|name|実際に表示されるカラム名|
|第5引数<br>(オプション)|{}|`include_blank`という値のない選択肢を先頭にするオプションなどがある|
|第6引数<br>(htmlオプション)|{class:"genre-select"}|今回はクラス名を付与(cssを当てるため)|

```erb
<%= form_with model: @article, url:articles_path, local: true do |f| %>
  <!-- プルダウンが生成される -->
  <%= f.collection_select(:genre_id, Genre.all, :id, :name, {}) %>
  <%= f.submit "投稿する" %>
<% end %>
```

[![Image from Gyazo](https://i.gyazo.com/bef22e3105f91276532e26ccfaa8f278.png)](https://gyazo.com/bef22e3105f91276532e26ccfaa8f278)

# まとめ(ヘルパーメソッド)
## form_withメソッド
フォームを実装するためのヘルパーメソッド
HTMLの`form`タグの代わりに使用する
[サンプルコード](https://github.com/likapantrip/form_app)を参照

### 記述
`do`から`end`までがフォームとして認識される

```erb
<%= form_with url: "/posts", method: :post, local: true do |f| %>
  <!-- 処理記述 -->
<% end %>
```

#### urlオプション
urlオプションに指定されたリクエストのパスに、フォームの情報を送る
コントローラーに、インスタンス変数の生成は不要

```erb
<%= form_with url: "/posts", method: :post, local: true do |form| %>
  <!-- 処理記述 -->
<% end %>
```

#### modelオプション
modelオプションに指定されたインスタンス変数の状態によってリクエストを送るアクションを自動的に判断し、フォームの情報を送る

インスタンス変数の状態とは、インスタンス変数に保存されている内容のこと

||新規作成|編集|
|---|---|---|
|フォーム送信|newアクションから、createアクションにフォーム情報を送信|editアクションから、updateアクションにフォーム情報を送信|
|インスタンス変数|中身は空|中身は空ではない|
|例|`@item = Item.new`|`@item = Item.find(params[:id])`|

コントローラーに、インスタンス変数を生成

```erb
<!-- コントローラーに、インスタンス変数@tweetを生成-->

<%= form_with(model: @item, local: true) do |f| %>
  <!-- 処理記述 -->
<% end %>
```

#### 親子関係のデータ送信
[こちら](https://qiita.com/likapantrip/items/66b03d482f57b1a6aa4f)を参照

### 引数
|オプション名|説明|
|---|---|
|urlオプション|フォームの情報を送るリクエストのパスを指定|
|modelオプション|インスタンス変数を指定し、リクエストのパスを自動判断|
|methodオプション|フォームの情報を送るリクエストのHTTPメソッドを指定。オプションの初期値は`:post`なので、`post`メソッドを指定する場合は省略することが可能|
|localオプション|リモート送信であるAjaxでの通信を無効にするかどうかを指定。`true`にすると無効になる|

[![Image from Gyazo](https://i.gyazo.com/be6a90b9062a9d91fc25d7e5e577957e.png)](https://gyazo.com/be6a90b9062a9d91fc25d7e5e577957e)

### フォームの部品を生成する主なヘルパーメソッド
#### label
フォームの項目名を表示する
- 引数
    - name属性にあたる名前が入る
    - テーブルのカラム名がフォームの項目名として表示される

#### text_field
1行のテキストボックス
- 引数
    - name属性にあたる名前が入る
    - name属性の値がデータを扱う際の名前であるキーになる
- maxlengthオプション
    - 入力できる最大文字数を指定する
    - 最大文字数を超過して登録しようとした場合、最大文字数に自動でカットされる
    - `maxlength: "6"`は最大6文字入力できる

#### number_field
1行の数値入力ボックス(数字を増減させるためのボタンが利用可能)
- 引数
    - name属性にあたる名前が入る
    - name属性の値がデータを扱う際の名前であるキーになる

#### password_field
パスワード入力ボックス(入力したテキストがアスタリスクなどに置き換えて表示される)
- 引数
    - name属性にあたる名前が入る
    - name属性の値がデータを扱う際の名前であるキーになる

#### check_box
チェックボックス(複数選択可能)
- 引数
    - name属性にあたる名前が入る
    - name属性の値がデータを扱う際の名前であるキーになる

#### radio_button
ラジオボタン(複数の中から1つしか選択できない)
- 引数
    - name属性にあたる名前が入る
    - name属性の値がデータを扱う際の名前であるキーになる

#### submit
送信ボタン
- 引数
    - 送信ボタンに表示する文字列になる

#### 全体
- autofocusオプション
    - `autofocus: true`を記述したフォームに、カーソルがあたった状態でページが開く

### 検索フォーム
```erb
<!-- collectionを使用し、tweetsコントローラーにsearchアクションのルーティングを作成 -->

<%= form_with(url: search_tweets_path, local: true, method: :get) do |f| %>
  <%= f.text_field :keyword, placeholder: "投稿を検索する" %>
  <%= f.submit "検索" %>
<% end %>
```

### select要素とoption要素
プルダウンのようなセレクトボックスを作成する
詳細は、[こちら](https://qiita.com/likapantrip/items/5cd8625437aefe0614ef#select要素)を参照

```erb
<!-- DBに登録されている全ユーザーを選択肢として表示する -->

<select name="room[user_ids][]">
  <option value="">チャットするユーザーを選択してください</option>
  <% User.all.each do |user| %>
    <option><%= user.name %></option>
  <% end %>
</select>
```

## link_toメソッド
リンクを作成するためのヘルパーメソッド
HTMLの`a`タグの代わりに使用する

### 記述方法
#### URL指定

```erb
<%= link_to 'リンクに表示する文字', 'リンク先のURL' %>

<%= link_to 'Googleへ移動', 'https://www.google.co.jp' %>
```

#### パス指定

```erb
<%= link_to 'リンクに表示する文字', 'パス', method: :HTTPメソッド %>

<%= link_to '新規投稿ページへ移動', '/posts/new', method: :GET %>
```

#### Prefix

```erb
<%= link_to 'リンクに表示する文字', Prefix_path %>

<%= link_to '新規投稿ページへ移動', new_post_path %>
```

### メソッド別対応
#### GETメソッド
`method`を削除可能であるため、基本的には記述しない

```erb
<%= link_to 'リンクに表示する文字', 'パス' %>

<%= link_to '新規投稿ページへ移動', '/posts/new' %>
<%= link_to '新規投稿ページへ移動', new_post_path %>
```

#### DELETEメソッド
削除対象を区別するために、テーブルのidカラムを指定する
`data: { turbo_method: :delete }`を記述する

```erb
<!-- リンクに表示する文字をクリックすると、URIパターン+削除対象(テーブルのidカラム ※値はパラメーターとして連携される)とDELETEメソッドのリクエストを送信する -->
<%= link_to 'リンクに表示する文字', "URIパターン/#{テーブル.id}", data: { turbo_method: :delete } %>

<!-- 削除リンクをクリックすると、URIパターン(/tweets/)+削除対象(tweetsテーブルのidカラム)とDELETEメソッドのリクエストを送信する -->
<%= link_to '削除', "/tweets/#{tweet.id}", data: { turbo_method: :delete } %>
<%= link_to '削除', tweet_path(tweet.id), data: { turbo_method: :delete } %>
```

## image_tagメソッド
imgタグを生成するためのヘルパーメソッド

- 第一引数に画像ファイルを指定する
    - `app/assets/images`配下の画像ファイル
    - `public`配下の画像ファイル
        ファイル名の前に`/`が必要
    - `モデル.画像ファイル名`

```erb
<!-- app/assets/image/menu.pngを指定する -->
<%= image_tag 'menu.png' %>

<!-- public/menu.pngを指定する -->
<%= image_tag '/menu.png' %>

<!-- ファイルをモデルから指定する -->
<%= image_tag モデル.画像ファイル名 %>
<%= image_tag tweet.image %>
```

# Ruby on Railsまとめ
https://qiita.com/likapantrip/items/46b43c9d1309b6633f0a

# ビュー
https://qiita.com/likapantrip/items/7773987cdd641ea3aad9