10章。
まず、partial に切り出すところはこんな感じになるでしょうか。
new.html.erb にて、form_for 周りを選択します。
右クリックから Refactor → Extract → Partial で切り出します。
名前をつけます。チュートリアルに従って _form.html.erb とします。
これで切り出せました。
あとは少々調整します。new.html.erb と edit.html.erb の差分を見て、共通化できる部品を活かして、違うところは provide で渡します。
このスクリーンキャプチャでは form_for の一つ上も切り出してしまったのですが、gravatar_for があることに気が付いて調整しています。
new.html.erb
<% provide(:title, 'Sign up') %>
<% provide(:url, signup_path) %>
<% provide(:button_text, 'Create my account') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 offset-md-3">
<%= render 'form' %>
</div>
</div>
edit.html.erb
<% provide(:title, 'Edit user') %>
<% provide(:url, user_path) %>
<% provide(:button_text, 'Save changes') %>
<h1>Update your profile</h1>
<div class="row">
<div class="col-md-6 offset-md-3">
<%= render 'form' %>
<div class="gravatar_edit">
<%= gravatar_for @user %>
<a href="http://gravatar.com/emails" target="_blank">Change</a>
</div>
</div>
</div>
_form.html.erb
<%= form_for(@user, url: yield(:url)) do |f| %> <%= render 'shared/error_messages', object: @user %> <%= f.label :name %> <%= f.text_field :name, class: 'form-control' %> <%= f.label :email %> <%= f.email_field :email, class: 'form-control' %> <%= f.label :password %> <%= f.password_field :password, class: 'form-control' %> <%= f.label :password_confirmation, "Confirmation" %> <%= f.password_field :password_confirmation, class: 'form-control' %> <%= f.submit yield(:button_text), class: "btn btn-primary" %> <% end %>
10.1.3 の演習では、テストを追加します。
わたしはブラウザに Chrome を使っているのですが、実際にエラー画面を表示させて右クリックから「検証」をするとこのようになります。
div.alert を指定すればいいということがわかるので、assert_test に追加します。
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "unsuccessful edit" do
get edit_user_path(@user)
assert_template 'users/edit'
patch user_path(@user), params: { user: { name: "",
email: "foo@invalid",
password: "foo",
password_confirmation: "bar" } }
assert_template 'users/edit'
assert_select "div.alert", "The form contains 4 errors."
end
end
10.2.3 の演習でもテストを追加するのがありました。
/users/1/edit にアクセスする → ログインが求められる → ログインしたら /users/1/edit に戻って編集できるようになる、という確認で、ログイン前後での session[:forwarding_url] の値をチェックしておきましょうというテストです。
こんな感じにしてみました。
test "successful edit with friendly forwarding" do
get edit_user_path(@user)
assert_equal edit_user_url(@user), session[:forwarding_url]
log_in_as(@user)
assert_redirected_to edit_user_url(@user)
assert_nil session[:forwarding_url]
name = "Foo Bar"
email = "foo@bar.com"
patch user_path(@user), params: { user: { name: name,
email: email,
password: "",
password_confirmation: "" } }
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal name, @user.name
assert_equal email, @user.email
end
リスト 10.39 の CSS では $gray-lighter を使っていますが、Bootstrap 4 にはありません。上の方で定義しておきます。
@import "bootstrap";
/* mixins, variables, etc. */
$gray: #555;
$gray-light: #777;
$gray-medium-light: #eaeaea;
$gray-darker: #222;
$state-danger-text: #f00;
$gray-lighter: #eee;
@mixin box_sizing {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
...
10.3.1 のテストは、右上のメニューのところがログインしていないときとログインしたときで変わるというのを追加してみました。
ログインしていないとき
ログインしたとき
site_layout_test.rb
require 'test_helper'
class SiteLayoutTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "layout links without login" 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=?]", users_path, count: 0
assert_select "a[href=?]", logout_path, count: 0
assert_select "a[href=?]", about_path
assert_select "a[href=?]", contact_path
get contact_path
assert_select "title", full_title("Contact")
end
test "layout links with login" do
log_in_as(@user)
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=?]", users_path
assert_select "a[href=?]", user_path(@user)
assert_select "a[href=?]", edit_user_path(@user)
assert_select "a[href=?]", logout_path
assert_select "a[href=?]", about_path
assert_select "a[href=?]", contact_path
end
end
10.3.3 では will_paginate を使います。bootstrap-will_paginate では Bootstrap 4 に対応していないようなので、will_paginate-bootstrap4 を使ってみました。
10章で Gemfile に追加した部分
# section 10 gem 'faker' gem 'will_paginate' #gem 'bootstrap-will_paginate' gem 'will_paginate-bootstrap4'
リスト 10.48 では div.pagination の要素があることを確認していますが、will_paginate-bootstrap4 では div ではなく ul になっていました。
require 'test_helper'
class UsersIndexTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "index including pagination" do
log_in_as(@user)
get users_path
assert_template 'users/index'
assert_select 'ul.pagination'
User.paginate(page: 1).each do |user|
assert_select 'a[href=?]', user_path(user), text: user.name
end
end
end
リスト 10.56 のテストはこう書きました。admin 属性を変更しようとしてもできません、というものです。
test "should not allow the admin attribute to be edited via the web" do
log_in_as(@other_user)
assert_not @other_user.admin?
patch user_path(@other_user), params: {
user: { password: "password",
password_confirmation: "password",
admin: true } }
assert_not @other_user.admin?
end
10章は長い道のりでした。テストを書きながら実際に動かして進めていくと楽しいですね。







