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.rb
にdebugger
を追記したら, 以下のコマンドでコンテナの標準入出力とローカルマシンのターミナルをアタッチします.
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の置換コマンドを使ってf
をfoobar
に書き換えましょう.
:%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 プロのデプロイ
省略.