ユーザーの情報のアップデート

前回は編集ページに移動しただけだった。ので
今回は編集内容を送信できるようにする。

# 情報のアップデート
## ルーティングの設定
```routes.rb
Rails.application.routes.draw do
.
.
.
  post 'users/:id/update' to: 'users#update'
end
```
## コントローラを作成
```users_controller.rb
.
.
.
  def edit
    @user = User.find_by(id: params[:id])
  end
.
.
.
```
## Routing Error
No route matches [GET] "/users/98"
Rails.root: /Users/hyoudoumasatomo/Repos/garden
```/users/98```がないと言っている。

```routes.rb
Rails.application.routes.draw do
.
.
.
  post 'users/:id/update' to: 'users#update'
end
```
```routes.rb
Rails.application.routes.draw do
.
.
.
  post 'users/:id/update', to: 'users#update'
end
```
```,```が無かったからだ。
成功！
## インスタンス変数を定義する
```users_controller.rb
.
.
.
  def edit
    @user = User.find_by(id: params[:id])
  end
end
```
## 編集ページに登録されている値を前もって入力
```edit.html
.
.
.
  <div>ユーザー情報編集</div>
  <div>
    <%= form_tag('/users/create', method: :post) do  %>
      <p>ユーザー名</p>
      <input name="name" value="<%= @user.name %>">
      <p>メールアドレス</p>
      <input name="email" value="<%= @user.email %>">
      <p>パスワード</p>
      <input name="password" value="<%= @user.password %>">
      <input type="submit" value=保存>
    <% end %>
  </div>
.
.
.
```
成功！

さあ送信機能を追加だ！

## コントローラにupdateアクションを定義する
```users_controller.rb
.
.
.
  def update
    @user = User.new(name: params[:name], email: params[:email], password: params[:password])
    redirect_to "users/#{@user.id}"
  end
end
```
### 更新されているかを確認
```
.
.
.
|  98 | tarou              | aaa@aaa   | aaa      |
|  99 | tarou              | aaa@aaa   | aaa      |
| 100 | tarou              | bbb@bbb   | aaa      |
+-----+--------------------+-----------+----------+
41 rows in set (0.00 sec)
```
太郎が新たに作られている。おかしい
やっぱりコントローラがおかしかったな。
progateを見た。

## コントローラを修正する
```users_controller.rb
.
.
.
  def update
    @user = User.find_by(id: params:[:id])
    @user.name = params[:name]
    @user.email = params[:email]
    @user.password = params[:password]
    redirect_to "users/#{@user.id}"
  end
end
```
mysqlのテーブルを見ると更新というよりか新しく作られているのでこれはまた今度調べてみたい。

## パスがおかしいと思う。
```
<%= form_tag("users/create", method: :post) do  %>
```
```
<%= form_tag("users/#{@user.id}/update", method: :post) do  %>
```
### Routing Error
No route matches [POST] "/users/103/users/103/update"

### ActionController::Redirecting::UnsafeRedirectError in UsersController#update
Unsafe redirect to "http://127.0.0.1:3000users/103", pass allow_other_host: true to redirect anyway.

```
  redirect_to "users/#{@user.id}"
```
```
  redirect_to "/users/#{@user.id}"
```

saveとsave！の違いは後で調べる

### ActiveRecord::RecordInvalid in UsersController#update
Validation failed: Email can't be blank, Email has already been taken

一応saveを今は使っていく。
```users_contorller
def update
    @user = User.find_by(id: params[:id])
    @user.name = params[:name]
    @user.email = params[:email]
    @user.password = params[:password]
    if @user.save
      flash[:notice] = "更新されました。"
      redirect_to "/users/#{@user.id}"
    else
      render "users/edit"
    end
```
```application.html
.
.
.
    <% if flash[:notice] %>
      <div class="flash">
        <%= flash[:notice] %>
      </div>
    <% end %>
.
.
.
```
これで表示された。

## saveとsave！の違い
save/save!メソッドはデータベースに保存をするためのメソッド
### save
保存に成功したらtrueを、保存に失敗(バリデーションに失敗)したらfalseを返します。
if/else文で保存できた場合、できなかった場合とで処理をわけると良いでしょう。

### save!
保存に成功したらtrueを返しますが、保存に失敗(バリデーションに失敗)したら例外が発生します。
保存できなかった場合の処理はrescue節で行う必要があります。

出典 https://techacademy.jp/magazine/22082

### save!を使うとき
transactionメソッドは例外が発生した場合にロールバックするので、保存に失敗したら例外を発生させなくてはいけません。

### トランザクション
1〜3までの複数の処理を1つの処理単位としてまとめる必要があり、このまとめる処理のこと

### if文でsave!を試して
elseに行く前にsave!の例外処理が発生してelseの処理が発生しなくなった。
これはやっぱりこの場合は適さないのかな。