Railsチュートリアル 第7章

7.1 ユーザーを表示する

7.1.1

演習1

以下の通りでした.

--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  controller: static_pages
  action: about
permitted: false

演習2

全く同じものが表示されました.

irb(main):002:0> puts user.attributes.to_yaml
---
id: 4
name: Michael Jackson
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2018-06-25 09:33:51.000000000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2018-06-25 09:41:15.000000000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$tM4ebAaSFIzfhqzi6.Lo/Ofs6/TfKpnP7LrgkCRV/z02U.CjwKubu"
=> nil

7.1.2

演習1, 2

こんな感じでしょうかね.

# app/views/users/show.html.erb
<%= @user.name %>, <%= @user.email %>,
<%= @user.created_at %>, <%= @user.updated_at %><br>

<%= Time.now %>

7.1.3

Dockerで環境を構築している場合は, Byebugを利用するためにひと工夫必要なようです. 詳しくはこちらに記載しました.

users_controller.rbdebuggerを追記したら, 以下のコマンドでコンテナの標準入出力とローカルマシンのターミナルをアタッチします.

docker attach <Rails' container name>

この状態で/users/1にアクセスすると, Byebugのプロンプトがターミナルに表示されます.

[1, 9] in /myapp/app/controllers/users_controller.rb
   1: class UsersController < ApplicationController
   2:   def show
   3:       @user = User.find(params[:id])
   4:       byebug
=> 5:    end
   6:   
   7:   def new
   8:   end
   9: end
(byebug)

paramsの内容をYAML形式で表示してみましょう.

(byebug)puts params.to_yaml
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  controller: users
  action: show
  id: '1'
permitted: false
nil

yメソッドも試してみます.

 (byebug) y params
*** NoMethodError Exception: undefined method `y' for #<UsersController:0x00007fe159010210>

Byebugではyメソッドは使えないみたいですね.

演習2

newアクションではインスタンスメソッドの@userは定義されていませんね.

7.1.4

演習1, 2

省略.

演習3

リスト7.12と7.13を見比べると, コードの量が異なりますね. ハッシュを引数にとる場合は, ハッシュの中から値を取り出すコードを書く必要があります. しかしキーワード引数であれば, それは不要です.

他にも, メソッドが予期していない引数を受け取った場合にも挙動が異なります. ハッシュ引数の場合, 以下のような誤った引数を指定してもエラーが発生しません.

grabatar_for @user, size: 100, shape: :square

ハッシュを受け取っている以上, 間違った引数と認識されないわけですね. しかしキーワード引数の場合, 上記のような引数を指定するとエラーが発生します. 定義していないキーワードが存在するからですね.

7.2 ユーザー登録フォーム

7.2.1

演習1

:name:nomeと書き換えユーザー登録ページにアクセスすると, 以下のようなエラーが表示されました.

undefined method `nome' for #<User:0x00007fe154bddef8>

演習2

Vimの置換コマンドを使ってffoobarに書き換えましょう.

:%s/f\./foobar\.

ファイル全体のf.foobar.に置換しています. これだけではブロック引数の|f|の部分は置換できないので, そこは手動で書き換えましょう.

以下のようにしてしまうと無駄なところまで置換されるので注意ですね.

:%s/f/foobar

この状態でユーザー登録ページにアクセスしても, 問題なく表示されます. では何が問題なのでしょうか...? わかりませんでした. でもあまりよくないとのことですから, 戻しておきました. 戻すときは以下のコマンドで良いですね.

:%s/foobar/f

7.2.2

演習1

いちいちHTMLタグを書くのなんて面倒ですもんね.

7.3 ユーザー登録失敗

7.3.1

Rails側ではシンボル, HTML側では文字列というのが少しややこしいですね.

7.3.2

演習1

省略.

7.3.3

演習1

省略.

演習2

入力データの検証に失敗した場合, createコントローラによって, newページがレンダリングされます. あくまでアクセスしているURLはcreateに対応する/usersということでしょうかね.

7.3.4

演習1

こちらを参考にしました.

assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
assert_select 'li', "Name can't be blank"
assert_select 'li', "Email is invalid"
assert_select 'li', "Password is too short (minimum is 6 characters)"
assert_select 'li', "Password confirmation doesn't match Password"

演習2

何が問題になっているかを整理しましょう.

config/routes.rbに以下のルーティングを設定しました.

post '/signup', to: 'users#create'

これによって, /signupへのPOSTリクエストに, createアクションが対応するようになりました.

しかしテストコードでPOSTリクエストをしているURLは/usersのままです.

assert_no_difference 'User.count' do
    post users_path, params: #略
end

それなのにテストをパスしまっているのはどうしてだろうというのが, この演習の問いです.

答えとしては, routes.rbに上記の設定をしたとしても, /usersへのPOSTリクエストとcreateアクションの対応は消えたわけではないとうことでしょうね.

演習3

以下のように変更し, テストにパスすることを確認しました.

assert_no_difference 'User.count' do
    post signup_path, params: #略
end

演習4

正しいアクションが指定されているかを確認するテストを書き加え, テストにパスすることを確認しました.

assert_select 'form[action="/signup"]'

7.4 ユーザー登録成功

7.4.1

演習1, 2

省略.

7.4.2

演習1, 2

省略.

7.4.3

演習1, 2

省略.

7.4.4

演習1

これまでのように, HTMLタグの有無を確認するテストをはじめは思いつきました.

assert_select 'div.alert-success'

flashが空でないかを確認するのであれば, 以下のように書けます.

assert_not flash.empty?

この書き方でテストがパスすることが確認できました. しかしこれだと演習2の変更がうまくいっているかどうかのテストはできませんね.

演習2, 3

省略.

演習4

データの保存に失敗した場合はリダイレクトが行われません. したがってテンプレートファイルのassertionでこのバグを検知することができます.

7.5 プロのデプロイ

省略.