RailsによるアジャイルWebアプリケーション開発

第14章 タスクI:ログイン

書籍にあるように、全てのテストに共通するbeforeの定義の仕方が分からなかったので、
Everyday Railsにあるように、LoginMacrosを定義して、各Controller Specでセットした。
ログイン画面ではform_tagではなくform_forを使うようにした。

  • app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  skip_before_action :authorize

  def new
    @user = User.new
  end

  def create
    @user = User.find_by(name: user_params[:name])

    if @user && @user.authenticate(user_params[:password])
      session[:user_id] = @user.id
      redirect_to admin_url
    else
      redirect_to login_url, alert: "無効なユーザ/パスワードの組み合わせです"
    end
  end

  def destroy
    session[:user_id] = nil
    redirect_to store_url, notice: "ログアウト"
  end

  private

  def user_params
    params.require(:user).permit(:name, :password)
  end
end
  • app/views/sessions/new.html.haml
.depot_form
  - if alert
    %p#notice= alert

  = form_for @user, url: login_url do |f|
    %fieldset
      %legend ログインしてください

      .field
        = f.label :name, "名前:"
        = f.text_field :name

      .field
        = f.label :password, "パスワード:"
        = f.password_field :password

      .field
        = f.submit "ログイン"
  • spec/support/login_macros.rb
module LoginMacros
  def login_as(user)
    session[:user_id] = user.id
  end

  def logout
    session.delete :user_id
  end
end
  • spec/controllers/users_controller_spec.rb
require 'rails_helper'

RSpec.describe UsersController, type: :controller do
  before do
    login_as create(:user)
  end

  describe "POST create" do
    let(:user) { attributes_for(:user) }

    it "should create yser" do
      expect { post :create, user: user }.to change(User, :count).by(1)
    end

    it "redirects to users#index" do
      post :create, user: user
      expect(response).to redirect_to users_path
    end
  end

  describe "PATCH update" do
    before do
      @user = create(:user)
    end

    let(:update_user) { attributes_for(:user) }

    it "should update user" do
      patch :update, id: @user, user: update_user
      @user.reload
      expect(@user.name).to eq update_user[:name]
    end

    it "redirects to users#index" do
      patch :update, id: @user, user: update_user
      expect(response).to redirect_to users_path
    end
  end
end
  • spec/controllers/sessions_controller_spec.rb
require 'rails_helper'

RSpec.describe SessionsController, :type => :controller do

  describe "GET new" do
    it "returns http success" do
      get :new
      expect(response).to have_http_status(:success)
    end
  end

  describe "GET create" do
    before do
      @user = create(:user)
    end

    context "with valid attributes" do
      it "should login" do
        post :create, user: { name: @user.name, password: @user.password }
        expect(response).to redirect_to admin_url
        expect(session[:user_id]).to eq @user.id
      end
    end

    context "with invalid attributes" do
      it "should fail login" do
        post :create, user: { name: @user.name, password: "miss" }
        expect(response).to redirect_to login_url
      end
    end
  end

  describe "GET destroy" do
    before do
      @user = create(:user)
    end

    it "should logout" do
      get :destroy
      expect(response).to redirect_to store_url
    end
  end
end