Rails チュートリアル　第7章　まとめ

#全体像の把握
/signupにGetリクエストが送られると、ルーティングが作動し、usersコントローラのnewアクションにふられて、Userの型を作成し、テンプレートとしてフォーム画面が返ってくる。
ブラウザ側で、フォームに入力すると、submitを押した時点で、/usersにPostリクエストが送られ、createアクションが呼ばれる。createアクションでは前回作成したバリデーションに通れば、保存し、showアクション(ユーザー詳細ページ）に飛ばし、失敗すれば、newアクション(フォーム画面）に戻す。


#RESTful
/user/1というurlは一致しているが、GetなりPatchなりの処理を変えていくことで、DBに行いたい処理を切り替える

`<%= debug(params) if Rails.env.development? %>`
paramsには、ブラウザからのリクエスト内容が入っている、それを画面に出力する
if以下は開発環境ならばという意味

resources :usersで、7つのルーティングが用意されるので、それに応じたアクションを作っていく
用意されたルーティングはrails routesで確認できる(patchとputで実際は8)

GET(urlを入力してenterを押すと発行されるもの) /user/id user#show
ローカル変数（user)とインスタンス変数(@user)ではスコープが違う
ローカル変数ではそのメソッド内、インスタンス変数はビューから呼び出したい時に呼び出すことができる

#showアクション -user詳細ページ
/users/:idにGETリクエストを送ると、表示

コントローラーでは、URLに使われているidがparamsに格納され、そのidを使って、すでにDBに保存されているUser情報のidを検索し、それを元にUser情報を取得

```user_controller.rb
def show 
  @user = User.find(params[:id]) # params[:id] = 2`
end
```
Viewでは@user.nameと画像を表示

-----
#Newアクション -新規登録ページ

/signupにGetリクエストを送ると、form画面が返ってくる、ここで入力された情報が@userに格納され、次に引き継がれる
newアクションを実行すると、createアクションがないとErrorが出る
newからcreateへ移行する仕組みは整っているということを意味する
form_forでSubmitを押したことにより、Postリクエストが/usersに送られており、それでcreateアクションが呼ばれている

コントローラーでは、User情報の型を作り、それを@userに格納している

```users_controller.rb
def new
   @user = User.new 
end
```

テンプレートでは、
1 bootstrapのデザイン上の設定
2 form_for(@user)とすることで、ここで入力された内容が全て@userに入る
それをcreateアクションで、paramsとして使う

3 labelはUserに入力する内容を教えるもので、text_fieldは実際に入力するフォームを作成。
そして入力された内容を:nameにより、nameというkeyのvalueとして保存 email,passも同様

4 Passwordconfirmationは長く、confirmationで十分わかるので、オプション引数で表示名を指定

5 ボタン作成、Userが押すと全ての値がparamsに格納される


```new.html.erb
% provide(:title), 'Sign up' %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3"> 1
    <%= form_for(@user) do |f| %> 2
      <%= f.label :name %> 3
      <%= f.text_field :name %> 

      <%= f.label :email %> 
      <%= f.email_field :email %> 

      <%= f.label :password %>
      <%= f.password_field :password %> 

      <%= f.label :password_confirmation, "Confirmation" %>　4
      <%= f.password_field :password_confirmation %>
      
      <%= f.submit "Create my account", class: "btn btn-primary" %> 5
    <% end %>
  </div>
</div>
```

#createアクション -DBへ保存
createアクションでは、フォームに入力された内容をDBに保存するか、あるいはバリデーションに弾かれると、フォーム画面に戻るようにしている

user情報は二重のハッシュ構造になっている
{user: !ruby/hash:ActiveSupport::HashWithIndifferentAccess}
のさらに、user:は
{name: ----} {email: ----}というハッシュを持っている

ダミーコード
1 rails consoleで試したように一度やりとりが終わっても、Modelを継承したクラスならば、再びその情報を取得することができるので、その情報を改めて取得している
2 User情報は二重のハッシュ構造になっているので
3 Validationが実行されるとユーザーオブジェクトかfalseを返す。rubyではfalseとnil以外はtrue、つまりユーザーオブジェクトもtrueだから。
valiが成功したら、ユーザーオブジェクトが返り、 インスタンスをDBに保存
  

```user_controller.rb
 def create
    @user = User.new #1
    @user.name = params[:user][:name] #2
    : # email,passwordも同様
    
    if @user.save  #3
       Success
    else
       Failure
    end
    
  end
```
このコードはさらにシンプルに書くことができる
User.new(name: ..., email: ..., password: ... ,)という書き方が可能であることから
params[:user]には全てのUser情報が入っている

```user_controller.rb
def create
    @user = User.new(params[:user])
    if @user.save 
    else
       render "new" #登録失敗なら、signupページを
    end
    
  end
```
ただ、paramsの中身を悪意のあるUserに変更される恐れがあるので

```rb:
params.require(:user).permit(:name, :email, :password, :password_confirmation)
# params[:user]からの変更
```
を使う
これを使うことで、paramsをチェックすることができ、指定した項目以外は無視する
メソッドとして独立させて使うと良い


#エラーメッセージの表示
今後もフォーム作る時に使うので、Partial化（第5章）


```
<%= render 'shared/error_messages' %>
```
class="form-control"はデザイン上の話なので、考えないでいい

1 Errorがひとつ以上あるなら表示
2 複数形にしてくれる
3 errors.full_messagesという配列にErrorが入っている
4 一つずつ表示



```shared._error_messages
<% if @user.errors.any? %> 1
  <div id="error_explanation">
    <div class="alert alert-danger">
      The form contains <%= pluralize(@user.errors.count, "error") %>. 2
      
    </div>
    <ul>
    <% @user.errors.full_messages.each do |msg| %> 3
      <li><%= msg %></li> 4
    <% end %>
    </ul>
  </div>
<% end %>
```

#失敗時のテスト
IntegrationTest
`rails generate integration_test users_signup`

```rb:
test "invalid signup information" do
    get signup_path # signupページに行く、GETリクエストを送る
    assert_no_difference 'User.count' do
      post users_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
  end

    
    # users_path = /users 　rails routesで分かる
    # /usersにPOSTリクエストを送る　= createアクションへ
    # その時に次のparamsを送る、nameを空にしたりしてわざと失敗するようにしている(invalid)
    # assert_noーを使い、User.countで調べたUser数が登録に失敗して変わってないことを確認
    # 失敗したら、newに戻るかどうかチェック
```

#ユーザー登録成功時
createアクション内で, if @user.saveの Success時

```rb:
def create
  @user = User.new(user_params)
  if @user.save 
    flash[:success] = "Welcome"
    redirect_to @User   
  else
  end
end

```

```ruby:
redirect_to "/users/#{@user.id}"
redirect_to user_path(@user.id)  #名前付きルートで書ける
redirect_to user_path(@user) 
#user_pathのデフォルトの挙動では、そのオブジェクトのid情報を渡すのでid要らない
redirect_to @user  => show
# redirectではデフォルトの挙動で、引数に@userを渡すとuser_path(@user)と同じと判断
```

ここにGETリクエストを送ってくれという指示、今回ならshowページへ行くように設定されている
renderはビューの表示

flashという特殊な変数にキーと値を入れると一時的に表示される、実際はメソッド

1 | key,value| 今回なら、|:success, Welcome to the sample - |
2 alert-< でbootstrapで定義された色合いを出すことができる

```
<% flash.each do |message_type, message| %> 1
   <div class="alert alert-<%= message_type %>"><%= message %></div>
      <% end %>
```