見出し画像

railsチュートリアル魔改造編 第18章 ログイン画面魔改造

第18章 ログイン画面改造編

ログイン画面を魔改造していきます。

いつものようにトピックブランチを作成します。

cd ~/environment/sample_app
git checkout -b rails-makaizou-18

18.1 ログイン画面はどこから飛ぶ?

基本的に、ヘッダーのログイン画面をクリックすると飛ぶ。
URLは/login
またはlogin_path

/sample_app/config/routes.rb
で、
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
がそれに該当する行
getは、入った時に実行されるイメージ
postは、ログイン画面でログインボタンが押された時に実行されるイメージ

18.2 ログイン画面の文字列を魔改造


/loginのビューは
/sample_app/app/views/sessions/new.html.erb
の通り

ここを書き弄っていく

文字列は、
f.label :hoge
となっていた部分を
f.label :hoge, "ホゲ"
みたいな感じで変更していくと書き換わる

ただし!チェックボックスの場合は注意!
表示文字列はspanで指定しているので同じようなノリで書き換えるとハマる。
※ハマった

18.3 ログイン画面のエラー文を魔改造

エラー文は、新規登録画面と異なり、全てオリジナルの文章なので変更しやすい。

form_forの仕様で、:sessionを使用しているので、sessionsコントローラのcreateを呼ぶようになっている。
/sample_app/app/controllers/sessions_controller.rb

ユーザーが有効化されていないときの警告文を変更する。
また、ルートページに飛ぶとユーザビリティが落ちると思ったので、ログイン画面を再表示するようにする。
このとき、flashに文字を入れているが、再表示なのでflash.nowに変更する必要がある。

ユーザーが存在していない場合のエラー文も変更する。

/sample_app/app/views/layouts/application.html.erb

ログインしたときになにもメッセージがないと寂しいので、ログインしたらおかえりなさいって表示するとまたログインしたくなるような気がする

ここまでで、rails testが失敗するはずである。

ログ
----------------------------
ec2-user:~/environment/sample_app (rails-makaizou-18) $ rails test
Running via Spring preloader in process 7992
Started with run options --seed 21867
FAIL["test_should_redirect_update_when_logged_in_as_wrong_user", UsersControllerTest, 1.9434154359996683]
test_should_redirect_update_when_logged_in_as_wrong_user#UsersControllerTest (1.94s)
       Expected false to be truthy.
       test/controllers/users_controller_test.rb:53:in `block in <class:UsersControllerTest>'
FAIL["test_should_redirect_edit_when_logged_in_as_wrong_user", UsersControllerTest, 2.026156476000324]
test_should_redirect_edit_when_logged_in_as_wrong_user#UsersControllerTest (2.03s)
       Expected false to be truthy.
       test/controllers/users_controller_test.rb:45:in `block in <class:UsersControllerTest>'
 74/74: [=================================] 100% Time: 00:00:02, Time: 00:00:02
Finished in 2.81768s
74 tests, 421 assertions, 2 failures, 0 errors, 0 skips
----------------------------

いずれの理由も、ログイン時に文字を表示するように変更したことで、テストに失敗するようになったこと。
ここは仕様変更で書き換わる可能性があるので、該当のテストコードはコメントアウトにする。


18.4 最後に

保存する

rails test
git add -A
git status

ログ
----------------------------
ec2-user:~/environment/sample_app (rails-makaizou-18) $ git status
On branch rails-makaizou-18
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)
       modified:   app/controllers/account_activations_controller.rb
       modified:   app/controllers/sessions_controller.rb
       modified:   app/views/sessions/new.html.erb
       modified:   app/views/users/new.html.erb
       modified:   config/routes.rb
       modified:   test/controllers/users_controller_test.rb
----------------------------

6ファイル修正したことを確認

git commit -m "add 18"
git checkout master
修正前ファイルをブログ用に保存しておく
git merge rails-makaizou-18
git push origin master
修正後ファイルをブログ用に保存しておく

そしてherokuの操作
source <(curl -sL https://cdn.learnenough.com/heroku_install)
git remote set-url heroku https://git.heroku.com/jun-killer-makaizou.git
heroku maintenance:on
git push heroku master
heroku maintenance:off

https://jun-killer-makaizou.herokuapp.com/

18.4.1 修正後


リスト18.01
app/controllers/account_activations_controller.rb
----------------------------
class AccountActivationsController < ApplicationController
 #メールアドレスからURLを辿ったあとに呼び出される
 def edit
   #メールアドレスを元に、テーブルから1件だけユーザー情報を取得する
   #params[:email]とparams[:id]は、本文のerb(viewのなんとかmailer)で作成される
   user = User.find_by(email: params[:email])
   
   #ユーザーが存在しており、有効化はまだ済んでおらず、ダイジェストとトークンが一致するとき
   #activatedはdb/migrate/〇〇_add_activation_to_users.rbに定義がある
   #authenticated?は/sample_app/app/models/user.rbに定義がある
   if user && !user.activated? && user.authenticated?(:activation, params[:id])
     #ユーザーを有効化する
     #app/models/user.rbに定義がある
     user.activate
     #ユーザーをログイン状態にする
     #app/helpers/sessions_helper.rbに定義がある
     log_in user
     
     #有効化に成功したときのメッセージを出力する
     flash[:success] = user.name+"さん、railsチュートリアル魔改造へようこそ!"
     
     #ユーザーページへ
     redirect_to user
   #認証になんらかの理由で失敗したとき
   else
     #有効化に失敗したときのメッセージを出力する
     flash[:danger] = "申し訳ありません。認証に失敗しました。パスワードの変更をお願いします。"
     #トップページへ
     redirect_to root_url
   end
 end
end
----------------------------

リスト18.02
app/controllers/sessions_controller.rb
----------------------------
class SessionsController < ApplicationController
 #ログイン画面が表示されたときは、アクションで特になにもしない
 #/sample_app/config/routes.rbによって/loginで飛ぶ
 def new
 end
 #ログイン画面でログインボタンを押したときに実行されるアクション
 #/sample_app/config/routes.rbによって/loginから飛ぶ
 def create
   # テーブルからユーザー情報を取得する
   user = User.find_by(email: params[:session][:email].downcase)
   
   # ユーザーが存在しており、かつパスワードが合っている場合
   if user && user.authenticate(params[:session][:password])
     # ユーザーが有効化されいる場合
     if user.activated?
       log_in user
       params[:session][:remember_me] == '1' ? remember(user) : forget(user)
       flash[:success] = user.name+'さん、おかえりなさい!'
       redirect_back_or user
     # ユーザーが有効化されいない場合
     else
       message  = "アカウントが承認されていないようです。\n"
       message += "お手数ですが、メールアドレスからアカウントの承認をお願いします。"
       
       #再表示の場合は、flashではなくflash.nowにする
       flash.now[:warning] = message
       
       #再表示
       render 'new'
     end
   #ユーザーが存在していない場合または
   else
     flash.now[:danger] = 'メールアドレスまたはパスワードに誤りがあります'
     render 'new'
   end
 end
 def destroy
   log_out if logged_in?
   redirect_to root_url
 end
end
----------------------------

リスト18.03
app/views/sessions/new.html.erb
----------------------------
<%#
ここに表示されるエラー文は
/sample_app/app/views/layouts/application.html.erb
で表示される
%>
<%#タブにログインと表示する  %>
<% provide(:title, "ログイン") %>
<h1>ログイン</h1>
<%#BootStrap適用 %>
<div class="row">
 
 <%# 3-6-3の割合で配置 %>
 <div class="col-md-6 col-md-offset-3">
   
   <%# フォーム %>
   <%= form_for(:session, url: login_path) do |f| %>
     <%= f.label :email, "メールアドレス" %>
     <%= f.email_field :email, class: 'form-control' %>
     <%= f.label :password, "パスワード" %>
     <%= link_to "(パスワードを忘れた場合はこちら)", new_password_reset_path %>
     <%= f.password_field :password, class: 'form-control' %>
     <%#
         do~endで括られた部分をラベルにしており、チェックボックスが含まれている
         ため本文を分けている
     %>
     <%= f.label :remember_me, class: "checkbox inline" do  %>
       <%= f.check_box :remember_me %>
       <span>ブラウザを閉じてもログイン状態を維持する</span>
     <% end %>
     <%# form_forで:sessionを指定しているので/sample_app/app/controllers/sessions_controller.rbのcreateを呼ぶ %>
     <%= f.submit "ログイン", class: "btn btn-danger" %>
   <% end %>
   <br>
   <p><%= link_to "新規会員登録はこちら!", signup_path %></p>
 </div>
</div>
----------------------------

リスト18.04
app/views/users/new.html.erb
----------------------------
<%#
 # /signup で呼ばれるアクション
 # app/views/users/new.html.erbへ
 def new
   #ユーザーを新規に作成する
   @user = User.new
 end
%>
<%# 見出しを新規登録にする %>
<% provide(:title, '新規登録') %>
<%# 見出しを新規登録にする %>
<h1>新規登録</h1>
<%# Bootstrapの機能で、12列に何を割り当てるか決める %>
<div class="row">
 <%# 空白3-入力スペース6-空白3の構成にする %>
 <div class="col-md-6 col-md-offset-3">
   <%# フォームを作成し、@userにデータを入れていく  %>
   <%= form_for(@user) do |f| %>
     
     <%# エラー文を出力する %>
     <%= render 'shared/error_messages', object: f.object %>
     
     <%# 名前 %>
     <%= 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, "パスワード(再入力)" %>
     <%= f.password_field :password_confirmation, class: 'form-control' %>
     <%# パスワード(再入力) %>
     <%# form_forで:userを指定しているので/sample_app/app/controllers/users_controller.rbのcreateを呼ぶ %>
     <%= f.submit "魔改造アカウントを作成する", class: "btn btn-danger" %>
   <% end %>
 </div>
</div>
----------------------------

リスト18.05
config/routes.rb
----------------------------
Rails.application.routes.draw do
 
 # ルートページ
 root   'static_pages#home'
 
 get    '/help',    to: 'static_pages#help'
 get    '/about',   to: 'static_pages#about'
 get    '/contact', to: 'static_pages#contact'
 
 # 新規登録ページは、/signup
 # app/controllers/users_controller.rbのnewアクションへ
 get    '/signup',  to: 'users#new'
 
 #ログイン画面へのルーティング
 #/sample_app/app/controllers/sessions_controller.rbへ
 get    '/login',   to: 'sessions#new'
 #ログイン画面
 #/sample_app/app/controllers/sessions_controller.rbへ
 post   '/login',   to: 'sessions#create'
 delete '/logout',  to: 'sessions#destroy'
 resources :users do
   member do
     get :following, :followers
   end
 end
 #アカウント有効化用ルーティングをeditのみ作成する
 #edit_account_activation_urlで、以下が実行される
 #app/controllers/users_controller.rbのeditアクション
 resources :account_activations, only: [:edit]
 
 
 resources :password_resets,     only: [:new, :create, :edit, :update]
 resources :microposts,          only: [:create, :destroy]
 resources :relationships,       only: [:create, :destroy]
end
----------------------------

リスト18.06
test/controllers/users_controller_test.rb
----------------------------
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
 def setup
   @user = users(:michael)
   @other_user = users(:archer)
 end
 
 test "should redirect index when not logged in" do
   get users_path
   assert_redirected_to login_url
 end
 
 test "should get new" do
   get signup_path
   assert_response :success
 end
 test "should redirect edit when not logged in" do
   get edit_user_path(@user)
   assert_not flash.empty?
   assert_redirected_to login_url
 end
 test "should redirect update when not logged in" do
   patch user_path(@user), params: { user: { name: @user.name,
                                             email: @user.email } }
   assert_not flash.empty?
   assert_redirected_to login_url
 end
 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:              @other_user.password,
                                           password_confirmation: @other_user.password,
                                           admin: true } }
   assert_not @other_user.reload.admin?
 end
 
 test "should redirect edit when logged in as wrong user" do
   log_in_as(@other_user)
   get edit_user_path(@user)
#    assert flash.empty?
   assert_redirected_to root_url
 end
 test "should redirect update when logged in as wrong user" do
   log_in_as(@other_user)
   patch user_path(@user), params: { user: { name: @user.name,
                                             email: @user.email } }
#    assert flash.empty?
   assert_redirected_to root_url
 end
 
 test "should redirect destroy when not logged in" do
   assert_no_difference 'User.count' do
     delete user_path(@user)
   end
   assert_redirected_to login_url
 end
 test "should redirect destroy when logged in as a non-admin" do
   log_in_as(@other_user)
   assert_no_difference 'User.count' do
     delete user_path(@user)
   end
   assert_redirected_to root_url
 end
 
 test "should redirect following when not logged in" do
   get following_user_path(@user)
   assert_redirected_to login_url
 end
 test "should redirect followers when not logged in" do
   get followers_user_path(@user)
   assert_redirected_to login_url
 end
end
----------------------------

18.4.2 本章のまとめ

チェックボックスの右に表示されている文字列は、他の入力フォームと異なり、シンボルの横に文字列を入れて表示文字列を変更できないので注意。
どの入力フォームも、newビューから送信ボタンを押すとcreateアクションに飛ぶ
新規登録時のflashの文字の表示方法と、ログイン時のflashの文字の表示方法は異なる。

有効化してない時にログインしてトップページに戻されるのはどうなんだろう?ということで再表示するようにした。


修正前

画像1

画像2

画像3

画像4


修正後

画像5

画像6

画像7

画像8


この記事が気に入ったらサポートをしてみませんか?