railsチュートリアル第１０章

パーテーションを使いコードを短くする
テストは
こうなるべきであるということを定義すること
どう動くべきなのかを理解していなければならない。

```rb
 # GET /users/:id/edit ユーザ情報を更新するとき
  def edit
    @user = User.find(params[:id])
    # デフォルトでは app/views/users/edit.html.erbにレンダリングされる
    #                                             （ページに飛ぶ）
    # しかしまだedit.html.erbがないので作る
  end
  
  def update
    @user = User.find(params[:id])  
    if @user.update(user_params)
      # 更新に成功した場合を扱う。
    else
      # @user.error <=== ここにデータが入っている
      render 'edit'
      # じゃなかったらeditページに飛ぶ
    end
  end
```

```
  test "successful edit" do
    get edit_user_path(@user)
    # edit_user_path(@user)を表示する
    assert_template 'users/edit'
    # editページが表示されるかをテストする
    name  = "Foo Bar"
    # nameを定義する
    email = "foo@bar.com"
    patch user_path(@user), params: { user: { name:  name,
                                              email: email,
                                              password:              "",
                                              password_confirmation: "" } }
    # 不十分なパスワードを置き換えする
    assert_not flash.empty?
    # わからん
    # 空じゃないよね？
    assert_redirected_to @user
    # わからん
    # @userがどうなっているかを検証する
    @user.reload
    # @userを再取得
    assert_equal name,  @user.name
    # 定義したnameと@userのnameが等しいかテストする
    assert_equal email, @user.email
  end
```
リダイレクトとは
あるページから別のページに転送すること

サンプルユーザーを生成するRubyスクリプト

```rb
# メインのサンプルユーザーを1人作成する
User.create!(name:  "Example User",
             email: "example@railstutorial.org",
             password:              "foobar",
             password_confirmation: "foobar")

# 追加のユーザーをまとめて生成する
99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  User.create!(name:  name,
               email: email,
               password:              password,
               password_confirmation: password)
end
```
ユーザーが無効な場合にfalseを返すのではなく例外を発生させる

```
$ rails db:migrate:reset
$ rails db:seed
```
上でリセットし、１００人のデータができる。


####ページネーション
1つのページに一度に30人だけユーザーを表示する
ユーザー全体を表示するのは多すぎるから

```html
<% provide(:title, 'All users') %>
<h1>All users</h1>

<%= will_paginate %>

<ul class="users">
  <% @users.each do |user| %>
    <li>
      <%= gravatar_for user, size: 50 %>
      <%= link_to user.name, user %>
    </li>
  <% end %>
</ul>

<%= will_paginate %>`
```

```
 def index
    @users = User.paginate(page: params[:page])
 end
```
####ユーザーの削除
そのために
ユーザー削除の権限を持つadminクラスを作成

```
 rails generate migration add_admin_to_users admin:boolean
```
webページにオブジェクトを晒すことは攻撃される危険がある。
Strong Parametersを使って対策をする。
Strong Parametersについてはまだ理解していない。

####destroyアクション
destroyアクションへのリンクを追加
管理ユーザーへのアクセスを制限します
All usersにdeleteが表示される

```html
<li>
  <%= gravatar_for user, size: 50 %>
  <%= link_to user.name, user %>
  <% if current_user.admin? && !current_user?(user) %>
  <!--.adminで管理者であるかを確認かつwebのユーザーであるならば-->
    | <%= link_to "delete", user, method: :delete,
                                  data: { confirm: "You sure?" } %>
  　<!--deleteのリンク、delete（削除）を行うことができる-->
  　 <!--user_path(user) => DELETE /users/:id => destroy -->
  　 <!--userでidをもとにとれ出されDELETEで消される-->
  <% end %>
</li>
```
destroyアクションの内容

```rb
 def destroy
  # destroyアクション
    User.find(params[:id]).destroy
    # 任意のidのユーザーを削除する
    flash[:success] = "User deleted"
    # 削除のメッセージを表示する
    # [:success]なので緑
    redirect_to users_url
    # users_urlのページに移動する
  end
```

まだこの状態では誰でも削除をすることができるらしいので
自分が管理者であるかを確認する必要がある。
users_controller

```rb
class UsersController < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
  # ログインしていないユーザーが保護されたページに
    # アクセスしようとした際のケースについて対処
  # ログインしていない場合に
    # ログインページにリダイレクトさせるヘルパーメソッド
  # 何らかの処理が実行される直前に特定のメソッドを実行する
  # :editと:updateアクションだけにこのフィルタが適用される
  # :edit,:updateアクションが呼び出されたらlogged_in_userを行う
 
  # メソッドを呼び出すときは基本シンボルで呼び出す
  # メソッド名を引数に渡すときはシンボルで呼ぶ
  before_action :correct_user,   only: [:edit, :update]
  before_action :admin_user,     only: :destroy
  # 管理者だけが実行させる [:destroy]でも書いていいい。 
.
.
.

 # 管理者かどうか確認
    def admin_user
      redirect_to(root_url) unless current_user.admin?
      # current_userがadminでなければroot_urlのページに飛ぶ
    end
end
```
テスト用のユーザに管理者権限を与える

```
michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>
  admin: true
.
.
.

```

管理者権限を制御を行う

```rb
require 'test_helper'

class UsersIndexTest < ActionDispatch::IntegrationTest
  def setup
    @admin     = users(:michael)
    @non_admin = users(:archer)
  end

 test "index as admin including pagination and delete links" do
    log_in_as(@admin)
    get users_path
    assert_template 'users/index'
    assert_select 'div.pagination'
    first_page_of_users = User.paginate(page: 1)
    first_page_of_users.each do |user|
      assert_select 'a[href=?]', user_path(user), text: user.name
      unless user == @admin
        assert_select 'a[href=?]', user_path(user), text: 'delete'
      end
    end
    assert_difference 'User.count', -1 do
      delete user_path(@non_admin)
    end
  end

  test "index as non-admin" do
    log_in_as(@non_admin)
    # 管理者以外のユーザーがログインして
    get users_path 
    # users_pathにアクセスする
    assert_select 'a', text: 'delete', count: 0
    # deleteのリンクは表示されていない（0回）よね?,
  end
end

```

####ためになった話
テストとはこれはこうあるべきと定義するもの
何かを作りたいと思ったら
テストを作り、ある程度ルールを決めておくことを学んだ。
頑張りたい。

####困ったこと
deleteのリンクが表示されると思ったが
表示されなかった。　困った。
テキストではJavaScriptの云々と書いてあったが、そう言うような操作をしていないと思った。
なので
自分がログインしているのが管理者ではないアカウントでログインしているのかと予想を立てた。
そのためにコードにemailとpasswordを入力してみたら
daleteのリンクが表示された。
予想が当たって嬉しかった。
これからも努力したい。