0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Railsチュートリアル 第5章 - レイアウトを作成する…ユーザー登録: 最初のステップ

Posted at

概要

ユーザ登録ページへのルーティングを作成します。その前提条件として、2つ目のコントローラを作成します。この先実装していくユーザ登録機能の第一歩です。

Usersコントローラ

Usersコントローラの生成

StaticPagesコントローラに次ぐ2つ目のコントローラとして、Usersコントローラを生成します。まず現時点では、新規ユーザー用のユーザー登録ページ(スタブ)のみを実装した、最も簡単な形でコントローラの生成・実装を行っていきます。

コントローラの作成はrails generate controllerコマンドで行います。コントローラ作成のために与える引数は、以下の通りとします。

  • コントローラ名…Users
  • 最初に定義するアクション名…new
# rails generate controller Users new
Running via Spring preloader in process 1812
      create  app/controllers/users_controller.rb
       route  get 'users/new'
      invoke  erb
      create    app/views/users
      create    app/views/users/new.html.erb
      invoke  test_unit
      create    test/controllers/users_controller_test.rb
      invoke  helper
      create    app/helpers/users_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss

rails generage controller Users newにより、以下のリソースが生成されました。

  • Usersコントローラ
  • users/newへのGETリクエストに対するルーティング情報
  • usersビュー
  • Usersコントローラに対するテスト
  • users_helperヘルパー
  • usersに対するCoffeeScript形式のスクリプト
  • usersに対するSCSS形式のスタイルシート

現時点におけるUsersコントローラとその周辺リソース

生成されたばかりのUsersコントローラのソースコードは、以下のようになっています。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  def new
  end
end

app/controllers/users_controller.rbのコードから、以下のことがわかります。

  • UsersControllerクラスが定義されている
    • UsersControllerクラスは、ApplicationController`クラスを継承している
  • UsersControllerクラスでは、newメソッドが定義されている

続いて、生成されたばかりのapp/views/users/new.html.erbのソースコードは以下の通りです。

app/views/users/new.html.erb
<h1>Users#new</h1>
<p>Find me in app/views/users/new.html.erb</p>

さらに、生成されたばかりのtest/controllers/users_controller_test.rbのソースコードは以下の通りです。

test/controllers/users_controller_test.rb
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest
  test "should get new" do
    get users_new_url
    assert_response :success
  end

end

この時点で、テストは問題なく通ります。

# rails test
...略

  8/8: [=============================================================================================================================================================] 100% Time: 00:00:06, Time: 00:00:06

Finished in 6.55124s
8 tests, 18 assertions, 0 failures, 0 errors, 0 skips

演習 - Usersコントローラ

1. 表 5.1を参考にしながらリスト 5.41を変更し、users_new_urlではなくsignup_pathを使えるようにしてみてください。

  require 'test_helper'

  class UsersControllerTest < ActionDispatch::IntegrationTest
    test "should get new" do
-     get users_new_url
+     get signup_path
      assert_response :success
    end

  end

2. 先ほどの変更を加えたことにより、テストがredになったことを確認してください。なお、この演習はテスト駆動開発 (コラム 3.3) で説明したred/greenのリズムを作ることを目的としています。このテストは次の5.4.2greenになるよう修正します。

# rails test
...略

ERROR["test_should_get_new", UsersControllerTest, 1.619302900013281]
 test_should_get_new#UsersControllerTest (1.62s)
NameError:         NameError: undefined local variable or method `signup_path' for #<UsersControllerTest:0x0000558df747d378>
            test/controllers/users_controller_test.rb:5:in `block in <class:UsersControllerTest>'

  8/8: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.71337s
8 tests, 17 assertions, 0 failures, 1 errors, 0 skips

無事(?)テスト結果で不適合が指摘されました。「signup_pathというメソッドが定義されていない」という不適合ですね。Railsにおけるエンドポイントの扱いにおいて、_path_urlで終わるメソッドは、名前付きルートを定義したときに自動で定義されるのでしたね。必要になるのは、/signupというエンドポイントです。

ユーザー登録用URL

ユーザー登録ページのエンドポイントの変更

表 5.1でも言及されていたように、新規ユーザー登録ページのURLは、/users/newではなくて/signupにしたいです。ルーティングの変更が必要になります。

ルーティングの変更なので、ここで変更するファイルは、config/routes.rbです。では早速、先ほどの演習でも登場した/signupというエンドポイントを早速定義してみましょう。

config/routes.rb
  Rails.application.routes.draw do
-   get 'users/new'

    root 'static_pages#home'
    get '/help', to: 'static_pages#help'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
+   get '/signup', to: 'users#new'
  end

改めてrails testを実行してみます。

# rails test
...略

  8/8: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.55368s
8 tests, 18 assertions, 0 failures, 0 errors, 0 skips

先ほどの演習の内容と合わせて、これでテストが通るようになったのが確認できます。

Homeページのボタンに、ユーザー登録ページへのリンクを追加

先ほど行ったルーティングの変更で、/signupに対し、signup_pathsignup_urlというメソッドを呼び出せるようになりました。早速Homeページに/signupへのリンクを追加しましょう。リダイレクトではないので、signup_pathのほうを使います。

app/views/static_pages/home.html.erb
  <div class="center jumbotron">
    <h1>Welcome to the Sample App</h1>

    <h2>
      This is the home page for the
      <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      sample application.
    </h2>

-   <%= link_to "Sign up now!", '#', class: "btn btn-lg btn-primary" %>
+   <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
  </div>

  <%= link_to image_tag("rails.png", alt: "Rails logo"),
              'http://rubyonrails.org/' %>

最後に、signupページ用のビューのスタブの先頭に、app/views/layouts/application.html.erbを参照するための設定を追加します。ページタイトルは'Sign up'とします。

app/views/users/new.html.erb
+ <% provide(:title, 'Sign up') %>
  <h1>Users#new</h1>
  <p>Find me in app/views/users/new.html.erb</p>

この部分は、app/views/layouts/application.html.erbの以下の部分に展開されるのでしたね。

```erb:app/views/layouts/application.html.erb(抜粋)
<%= yield %>


現時点で、/signupをブラウザで表示した結果は以下のようになります。

<img width="1164" alt="スクリーンショット 2019-09-28 10.26.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/4d0b4a59-6935-5ee8-b8e8-9c9b1479cd08.png">

# 演習 - ユーザー登録用URL

## 1.1. もしまだ[5.4.1.1](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#sec-exercises_users_controller)の演習に取り掛かっていなければ、まずは[リスト 5.41](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-user_new_test)のように変更し、名前付きルートsignup_pathを使えるようにしてください。

この部分は、先ほどの演習で変更した部分となります。

## 1.2. また、[リスト 5.43](https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#code-signup_route)で名前付きルートが使えるようになったので、現時点でテストが`green`になっていることを確認してください。

rails test

...略

8/8: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.70987s
8 tests, 18 assertions, 0 failures, 0 errors, 0 skips


きちんとテストは通りますね。

## 2.1. 先ほどのテストが正しく動いていることを確認するため、signupルートの部分をコメントアウトし、テスト redになることを確認してください。

`config/routes.rb`を、以下のように変更します。

```diff:config/routes.rb
  Rails.application.routes.draw do
    get 'users/new'

    root 'static_pages#home'
    get '/help', to: 'static_pages#help'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
-   get '/signup', to: 'users#new'
+ # get '/signup', to: 'users#new'
  end
# rails test
...略

ERROR["test_should_get_home", StaticPagesControllerTest, 0.4042917999904603]
 test_should_get_home#StaticPagesControllerTest (0.41s)
ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method `signup_path' ...略

ERROR["test_should_get_root", StaticPagesControllerTest, 0.5494068999832962]
 test_should_get_root#StaticPagesControllerTest (0.55s)
ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method `signup_path' ...略

ERROR["test_layout_links", SiteLayoutTest, 2.0050760000012815]
 test_layout_links#SiteLayoutTest (2.01s)
ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method `signup_path' ...略

ERROR["test_should_get_new", UsersControllerTest, 2.0233185999968555]
 test_should_get_new#UsersControllerTest (2.02s)
NameError:         NameError: undefined local variable or method `signup_path' ...略

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

Finished in 2.07825s
8 tests, 8 assertions, 0 failures, 4 errors, 0 skips

テストが通らなくなりました。signup_pathというメソッドが定義されていない、というエラーですね。/signupに対する名前付きルートが書かれていないとこうなります。

実際、現時点でsignup_pathメソッドは定義されていません。以下はrails consoleでの確認結果です。

>> app.signup_path
...略
NoMethodError (undefined method `signup_path' ...略)

2.2. 確認できたら、コメントアウトを解除してgreenの状態に戻してください。

config/routes.rb
  Rails.application.routes.draw do
    get 'users/new'

    root 'static_pages#home'
    get '/help', to: 'static_pages#help'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
- # get '/signup', to: 'users#new'
+   get '/signup', to: 'users#new'
  end
# rails test
...略

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

Finished in 2.18233s
8 tests, 18 assertions, 0 failures, 0 errors, 0 skips

今度はきちんとテストが通りますね。

>> app.signup_path
=> "/signup"

rails consoleでも、signup_pathメソッドが存在することが確認できました。

3.1. リスト 5.32の統合テストにsignupページにアクセスするコードを追加してください (getメソッドを使います)。

test/integration/site_layout_test.rb
  require 'test_helper'

  class SiteLayoutTest < ActionDispatch::IntegrationTest

    test "layout links" do
      get root_path
      assert_template 'static_pages/home'
      assert_select "a[href=?]", root_path, count: 2
      assert_select "a[href=?]", help_path
      assert_select "a[href=?]", about_path
      assert_select "a[href=?]", contact_path
      get contact_path
      assert_select "title", full_title("Contact")
+     get signup_path
+     assert_select "title", full_title("Sign up")
    end
  end

end

3.2.コードを追加したら実際にテストを実行し、結果が正しいことを確認してください。

# rails test:integration
...略

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.62317s
1 tests, 7 assertions, 0 failures, 0 errors, 0 skips

テストは問題なく通りました。

3.余談 signupページのSign upではなくSigh upにしたらテスト結果がredになることを確認します。

app/views/users/new.html.erb
+ <% provide(:title, 'Sign up') %>
- <% provide(:title, 'Sigh up') %>
  <h1>Users#new</h1>
  <p>Find me in app/views/users/new.html.erb</p>

このときのテスト結果は以下の通りになります。

# rails test:integration
...略

 FAIL["test_layout_links", SiteLayoutTest, 1.7456585000036284]
 test_layout_links#SiteLayoutTest (1.75s)
        <Sign up | Ruby on Rails Tutorial Sample App> expected but was
        <Sigh up | Ruby on Rails Tutorial Sample App>..
        Expected 0 to be >= 1.
        test/integration/site_layout_test.rb:15:in `block in <class:SiteLayoutTest>'

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.75320s
1 tests, 7 assertions, 1 failures, 0 errors, 0 skips

無事(?)不適合が指摘されました。

もちろん、app/views/users/new.html.erbの内容を元に戻しておくのも忘れずに。

app/views/users/new.html.erb
- <% provide(:title, 'Sigh up') %>
+ <% provide(:title, 'Sign up') %>
  <h1>Users#new</h1>
  <p>Find me in app/views/users/new.html.erb</p>

この先の方針

これにて、Railsチュートリアル第5章は一通り完走となりました。今後は、以下の機能を追加していくこととなります。

  • ユーザー登録
  • サインイン
  • サインアウト
  • マイクロポスト機能
  • 他のユーザーのフォロー機能
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?