railsチュートリアル第10章 編集の失敗 編集失敗時のテスト

###編集の失敗
編集に失敗した場合について扱っていきます。
updateアクションの作成をする

####ユーザーのupdateアクションの初期実装
app/controllers/users_controller.rb

```rb
class UsersController < ApplicationController
  
  def show
    @user = User.find(params[:id])
    # データベースからユーザー情報を取り出す
  end
  
  def new
    @user = User.new
    #新しくユーザーオプジェクトを作成する
    # オブジェクトの属性をつける
  end
  
  def create
    @user = User.new(user_params)
    # 外部メソッドを使う
    if @user.save
      # 保存の成功をここで扱う。
      log_in @user
      # 登録後に自動ログインするため
      flash[:success] = "Welcome to the Sample App!"
      # 成功時一度だけ表示されるメッセージ
      redirect_to @user
      # urlを指定して表示する
      # 保存成功したらurlを表示する
    else
      render 'new'
      # 保存に成功しなければnewアクションに移動する
      # 失敗したらまた戻る
    end
  end
  
  def edit
    @user = User.find(params[:id])
    # データベースから探す
  end
  
  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      # 更新に成功した場合を扱う。
    else
      render 'edit'
    end
  end
  
  private
  #外部から使えないようにする
  
    def user_params
    # Usersコントローラの内部でのみ実行される
    # Web経由で外部ユーザーにさらされない
       params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
      # paramsとは、フォームなどによって送られてきた情報（パラメータ）
      # を取得するメソッドのこと
      
      # requireメソッドで受け取るパラメータ群を、
      # permitメソッドで利用可能なパラメータ名を指定します。
      
      # require,permitはセキュリティーの問題らしい。
      
      # requireで:hogeを要求している
      # permitで許可されていない
      # ストロングパラメータは受け取る値に制限をかけている
      # 2つでストロングパラメータらしい
    end
end

```
###演習
1.
編集フォームから有効でないユーザー名やメールアドレス、パスワードを使って送信した場合、編集に失敗することを確認してみましょう。
確認

###編集失敗時のテスト
エラーを検知するための統合テストを書いていきましょう。

####統合テストを生成
```
ubuntu:~/environment/sample_app (updating-users) $ rails generate integration_test users_edit
Running via Spring preloader in process 6559
      invoke  test_unit
      create    test/integration/users_edit_test.rb
```
####編集の失敗に対するテスト
test/integration/users_edit_test.rb

```rb
 require 'test_helper'
 # test_helper.rbのパラメータ群を指定

class UsersEditTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "unsuccessful edit" do
    get edit_user_path(@user)
    # 編集ページを取得
    assert_template 'users/edit'
    # 編集ページが表示されているか？d
    patch user_path(@user), params: { user: { name:  "",
                                              email: "foo@invalid",
                                              password:              "foo",
                                              password_confirmation: "bar" } }

    # 上書きする
    # オプション引数かな？
    # HTTP の PATCH リクエストメソッドは、リソースへの部分的な変更を適用
    # 編集に用いられやすい
    # テストだからrequre,permitを使わなくていいのかな？
    assert_template 'users/edit'
  end
end
```
#####テスト
```
ubuntu:~/environment/sample_app (updating-users) $ rails tRunning via Spring preloader in process 8279
Started with run options --seed 50136

  30/30: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.60030s
30 tests, 70 assertions, 0 failures, 0 errors, 0 skips
```
###演習
1.リスト 10.9のテストに１行追加し、正しい数のエラーメッセージが表示されているかテストしてみましょう。ヒント: 表 5.2で紹介したassert_selectを使ってalertクラスのdivタグを探しだし、「The form contains 4 errors.」というテキストを精査してみましょう。

```rb
 require 'test_helper'
 # test_helper.rbのパラメータ群を指定

class UsersEditTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "unsuccessful edit" do
    get edit_user_path(@user)
    # 編集ページを取得
    assert_template 'users/edit'
    # 編集ページが表示されているか？d
    patch user_path(@user), params: { user: { name:  "",
                                              email: "foo@invalid",
                                              password:              "foo",
                                              password_confirmation: "bar" } }

    # 上書きする
    # オプション引数かな？
    # HTTP の PATCH リクエストメソッドは、リソースへの部分的な変更を適用
    # 編集に用いられやすい
    # テストだからrequre,permitを使わなくていいのかな？
    assert_template 'users/edit'
    assert_select "div", "alert"
  end

end
```

```
ubuntu:~/environment/sample_app (updating-users) $ rails t
Running via Spring preloader in process 8968
Started with run options --seed 41135

 FAIL["test_unsuccessful_edit", #<Minitest::Reporters::Suite:0x0000557d393d0e80 @name="UsersEditTest">, 3.456445838000036]
 test_unsuccessful_edit#UsersEditTest (3.46s)
        <alert> expected but was
        <sample app
            
              
                Home
                Help
                  Log in>..
        Expected 0 to be >= 1.
        test/integration/users_edit_test.rb:26:in `block in <class:UsersEditTest>'

  30/30: [============================] 100% Time: 00:00:03, Time: 00:00:03

Finished in 3.53432s
30 tests, 71 assertions, 1 failures, 0 errors, 0 skips
```
わからない。

#####答え
```rb
 require 'test_helper'
 # test_helper.rbのパラメータ群を指定

class UsersEditTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "unsuccessful edit" do
    get edit_user_path(@user)
    # 編集ページを取得
    assert_template 'users/edit'
    # 編集ページが表示されているか？d
    patch user_path(@user), params: { user: { name:  "",
                                              email: "foo@invalid",
                                              password:              "foo",
                                              password_confirmation: "bar" } }

    # 上書きする
    # オプション引数かな？
    # HTTP の PATCH リクエストメソッドは、リソースへの部分的な変更を適用
    # 編集に用いられやすい
    # テストだからrequre,permitを使わなくていいのかな？
    assert_template 'users/edit'
    assert_select "div.alert", "The form contains 4 errors."   
    # alertクラスのdivを探すことによってエラーのタグを探すことができる。
  end

end
```
これでエラーは起こらなかった。