noggy’s blog

自分用の備忘録です。。。

7.4 ユーザー登録成功

ここでは新規ユーザーを実際にDBに保存できるようにし、ユーザー登録フォームを完成させる。

することは、
(1)ユーザーを保存できるようにする。
(2)保存に成功するとユーザー情報をDBに登録し、登録されたユーザーのプロフィールを表示。
(3)保存を失敗した場合は、7.3のとおり。

7.4.1 登録フォームの完成

現状では、有効な情報を送信してもエラーが発生してしまう。原因はcreateアクションに対応するビューがないから。
createアクションに対応するビューを作成することもできるが、Railsの慣習に従って、ユーザー登録に成功した場合は別のページにリダイレクトするようにしてみる。具体的には、新しく作成されたユーザーのプロフィールページにリダイレクトしてみる。

def create
    @user = User.new(user_params)                                               
    if @user.save
      redirect_to @user ←①追加                                                      
    else
      render 'new'
    end
  end

private                                                                       

    def user_params                                                            
      params.require(:user).permit(:name, :email, :password,
                                  :password_confirmation)
    end

①:

redirect_to @user

というコードからRails

redirect_to user_url(@user)

というコードを推察してくれる。ちなみに、この部分をググる

redirect_to user_url(id: @user.id)

とも等価のようだ。なぜなら、reidirect_toの引数にモデルオブジェクト(今の場合@user)が渡されると、Railsは一意に表す値、つまり、idを取得するようだ。その結果、redirect_to user_url(id: @user.id)と等価になるわけ。
ここまでが上記(1)、(2)の実装。

7.4.2 flash

新規ユーザー登録完了後に、ウェルカムメッセージを表示させる。
ただし、2度目以降はそのページにメッセージを表示させないようにする。
このために、Railsではflashという特殊な変数を使う。この変数はハッシュのように扱う。

  def create
    @user = User.new(user_params)   
    if @user.save
      flash[:success] = "welcome to the Sample App!" ←①追加                 
      redirect_to @user                                                         
    else
      render 'new'
    end
  end

private                                                                       

    def user_params                                                            
      params.require(:user).permit(:name, :email, :password,
                                  :password_confirmation)
    end

①:flash変数に代入したメッセージは、リダイレクトした直後のページで表示できるようになる。

コンソールで確認
$ rails c
>> flash = { success: "It worked!", danger: "It falied." }
=> {:success=>"It worked!", :danger=>"It falied."}
>> flash.each do |key, value|
?> puts "#{key}"
?> puts "#{value}"
>> end
success
It worked!
danger
It falied.
application.html.erbへの記述

上のコンソールでのパターンに従って、flash変数の内容をwebサイト全体にわたって表示できるようにするには、次のコードになる。

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

①の次の埋め込みRuby

alert-<%= message_type %>

では、適用するCSSクラスをメッセージの種類によって変更するようにしている。どういうことかと言うと、例えば:successキーのメッセージが表示される場合、適用されるクラスは次のようになる。

alert-success

このとき、:successキーはシンボルだったが、テンプレートに反映させる際に埋め込みrubyが自動的に"success"という文字列に変換している点に注意!うーん、Rubyもすごい!よって、classとしてalert-successとすればclassごとに変更できる。このことより、キーの内容によって異なったCSSクラスを適用することができ、結果メッセージの種類によってスタイルを動的に変更させることができる。うーん、すごい!

ちなみにBootstrap CSSは、このようなflashのクラス用に次の4つのスタイルを持っている。

  • success
  • info
  • warning
  • danger

以上より、次のコードは

flash[:success] = "welcome to the Sample App!"

最終的につぎのようなHTMLになる。

<div class="alert alert-success">welcome to the Sample App!</div>

application.html.erb

<body>
    <%= render 'layouts/header' %>
    <div class="container">
      <% flash.each do |message_type, message| %> ←追加(message_typeがキー、messageが値)
        <div class="alert alert-<%= message_type %>"><%= message %></div>
      <% end %>
      <%= yield %>                                    
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>  
    </div>
  </body>

7.4.3 実際のユーザー登録

サンプルアプリでユーザー登録をしてみる。
名前を「Rails Tutorial」、メールアドレスを「example@railstutroal.org」として登録

7.4.4 成功時のテスト

ここでは有効な送信に対するテストを書く。これにより、アプリでの振る舞いを検証し、もし今後バグが埋め込まれたら、それを検知できるようになる。ここでの目的はDBの中身が正しいかどうかを検証する。

有効なユーザー登録に対するテスト

test/integration/users_signup_test.rb

test "valid signup information" do                                            
    get signup_path ←①                                                            
    assert_difference 'User.count', 1 do ←②                                       
      post users_path, params: { user: { name: ←③               
                                         email:                 "user@example.com",
                                         password:              "password",
                                         password_confirmation: "password" } }
    end
    follow_redirect!  ←④                                                        
    assert_template 'users/show' ←⑤                                               
  end

①:新規登録ページにアクセス
②:assert_difference(expressions, difference = 1, message = nil) {...}:yieldされたブロックで評価された結果である式の戻り値における数値の違いをテストする。ここでは、ブロック内の処理を実行する直前と、実行した直後のUser.countの値を比較。特に、比較した結果の差異(=1)について、値が変わっていればture、変わっていなければfalse
③:user_pathにユーザー情報をPOSTリクエストで送信
④:指定されたリダイレクト先(users/show)に移動しているか検証
⑤:assert_template(expected, message = nil):そのアクションで指定されたテンプレートが描写されているかをバリデーション。ここでは'users/show'テンプレートが描画されているか検証