心はいつもAirPucci (空元気でもいいから)

毎日がPucciを着ているような気分

RailsTutorial4.0を高速で復習する。8章。

      2014/01/29


仕様の探求

userモデルには、登録と認証、承認に必要なモデルは既に作ってあります。7章で実装したのはユーザー登録の機能でした。8章では認証の機能を作成することになります。

登録済みのユーザーが、再ログインするとき、つまりいったんログアウトして再ログインするとき、認証と承認が走ります。
認証は、アクセスしている人が確かにその人自信であることを確認すること。入力されたIDとパスワードがその人のもの確認することで行います。
承認は、認証後、その人がサービスを利用してよいと確認すること。アクセスコントロールによりサービス利用可能な範囲の確認が行われます。

ユーザーモデルは作ったのですが、これとは別に、ログイン状態を表す情報が必要になります。ユーザーモデルは自分でIDやパスワードを登録して作成するのですが、ログイン状態は入力して作成するのではなく、ユーザーの振る舞いに応じて変化させていくものなので、ちょっと勝手が違いますね。それでもRESTfulな情報っていうのがなかなか落ちなかった点でした。

git checkout -b sign-in-out
ブランチを作成しておきます。

8.1セッション、サインインの失敗、です。

セッションとは

セッションとは、2つのコンピュータの間、たとえばクライアント側のブラウザとサーバーで動作しているRailsとの間の、半永続的な接続のことです。

webの世界でよくセッションセッションていうけど、ようはクライアントとサーバがつながっている状態とか、そのつながっている道がある状態とか、そんな感じですね。

セッションは、RESTfulなリソースとして作成しておくと便利です。

ね。自分で入力して作成する情報じゃないのにRESTfulに作るって、まだ正直違和感感じますが、そういうものだそうです。

なぜ違和感感じるかというと、ユーザー情報とセッションでは、粒度もレイヤーも違うように感じるからですね。
ユーザー情報は更新頻度は少なく、データの取得スピードも人間レベルの遅さで十分。情報量としては大きい。だからDB保存、っていうのはわかる。でもセッションって部品のようなもの。ユーザーの振る舞いがトリガーになるけど、他の通信リソースの影響を受けて状態も変わりそうだし、アクセス毎に生まれて消える寿命の短い情報だし、レスポンスも速くないと。アーキテクチャ的にはDB保存じゃなくて、オンメモリでもっておくイメージ。

そう、RESTfulにするしActiveRecordで管理するっていうのはRailsでの表現の仕方なので、アーキテクチャ的には適切に配置できる、はず。
*=>RESTfulなリソースは必ずしもActiveRecord定義ではなかった。かつ、ActiveRecord定義=DBモデルあり、でもなかった。

Usersリソースのように (Usersモデルを経由して) データベースをバックエンドに持つリソースとは異なり、このSessionsリソースではcookiesを使用します。cookiesとは、ブラウザに保存される小さなテキストデータです。サインイン関連の作業の大半は、このcookiesをベースにして認証システムを構築することになります。

ちゃんと説明が書いてありました。

8.1.1 Sessionコントローラ、です。

Sessionを実装する

テストからではなく、コントローラから作っています。
8章からは、1回目のRailsTutorialではとりあえずコピペして終わらせた箇所で、理解不十分なところもあると思うので、順をおってやっていきます。

rails g controller Sessions --no-test-framework
rails g integration_test authentication_pages

セッションのテストスクリプトはauthentication_pagesにするのですね。

サインインページのイメージ

signin_mockup_bootstrap

URLはまだ不明、パス名はsignin_pathにするとのこと。

Signinページのテストを書く

Sessionはコントローラを作り、パス名を決めただけで、モデルはまだ&ページもまだですが、サインイン(ログイン)ページのテストを書きます。

リスト8.1 セッションのnewアクションとビューをテストする。
spec/requests/authentication_pages_spec.rb

require 'spec_helper'

describe "Authentication" do

  subject { page }

  describe "signin page" do
    before { visit signin_path }

    it { should have_content('Sign in') }
    it { should have_title('Sign in') }
  end
end

テストは失敗します。まだページ自体がない(contorollerは書いたけどviewはまだない)し、ルートも作っていません。

ルートを作る

リスト8.2 リソースを追加して標準のRESTfulアクションを設定する。
config/routes.rb

Twili::Application.routes.draw do
  root  'static_pages#home'
  match '/help',    to: 'static_pages#help',    via: 'get'
  match '/about',   to: 'static_pages#about',   via: 'get'
  match '/contact', to: 'static_pages#contact', via: 'get'

  resources :users
  match '/signup',  to: 'users#new',            via: 'get'

  resources :sessions, only: [:new, :create, :destroy]
  match '/signin',  to: 'sessions#new',         via: 'get'
  match '/signout', to: 'sessions#destroy',     via: 'delete'
end

まだsessionsのモデル切っていませんが、route.rbに書いてしまいました。パスはできているはず。rake routesしてみます。

     Prefix Verb   URI Pattern               Controller#Action
       root GET    /                         static_pages#home
       help GET    /help(.:format)           static_pages#help
      about GET    /about(.:format)          static_pages#about
    contact GET    /contact(.:format)        static_pages#contact
      users GET    /users(.:format)          users#index
            POST   /users(.:format)          users#create
   new_user GET    /users/new(.:format)      users#new
  edit_user GET    /users/:id/edit(.:format) users#edit
       user GET    /users/:id(.:format)      users#show
            PATCH  /users/:id(.:format)      users#update
            PUT    /users/:id(.:format)      users#update
            DELETE /users/:id(.:format)      users#destroy
     signup GET    /signup(.:format)         users#new
   sessions POST   /sessions(.:format)       sessions#create
new_session GET    /sessions/new(.:format)   sessions#new
    session DELETE /sessions/:id(.:format)   sessions#destroy
     signin GET    /signin(.:format)         sessions#new
    signout DELETE /signout(.:format)        sessions#destroy

prefixにsigninがあるのでsignin_pathができました。/session/newが/signinでアクセスできるようになっています。
signout_pathも作っています。/session/destroyが/signoutでアクセスできるようになっています。

controllerにactionを書く

Sessionsのnew,destoroyのルートを作ったので、controllerには、new,create,destroyを作っておきます。

リスト8.3 最初のSessionsコントローラ。
app/controllers/sessions_controller.rb

class SessionsController < ApplicationController

  def new
  end

  def create
  end

  def destroy
  end
end

とりあえずのSigninページを作る

リスト8.4 最初のサインインビュー。
app/views/sessions/new.html.erb

<% provide(:title, "Sign in") %>
<h1>Sign in</h1>

これでテストはパスしました。

次は、
8.1.2サインインをテストする
からです。

いったんコミットしておきます。

 - テクニカル ,

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

  関連記事

no image
ブログは独自ドメインの方が強いかもね

すっかり月一ペースで更新するブログになってしまい焦ります。 震災直後に政権批判し …

教育のためならば、iPadアプリ料金なんて青天井ですわ

今年4月、USでのiPad発売。姪の中学入学祝いにちょうどいいなと思っていたら日 …

no image
formatはどこから取ってくる?

ruby on rails3プリケーションプログラミングの本の内容をruby2. …

no image
RailsTutorial4.0を高速で復習する。3.1章。

3.1章は静的ページの追加。これをトップページとして後で色々追加していきます。 …

no image
RailsTutorial4.0を高速で復習する。3.3.3章。

3.3.3埋め込みRubyです。viewにrubyコードを埋め込んでtitleを …

no image
RailsTutorial4.0を高速で復習する。9.2.3章。

9.2.3フレンドリーフォワーディング、です。 ログオンしていないユーザーが編集 …

railsでtest unitを生成させない

ruby on rails3プリケーションプログラミングの本の内容をruby2. …

no image
Everyday Rails3章 バリデーションをテストする

さっき、Aaronを削除したらテスト失敗することを確認しましたが、名前入力無しの …

no image
RailsTutorial4.0を高速で復習する。3.3.4章。

3.3.4レイアウトを使って重複を解消する、です。 ここでapplication …

Mac miniの液晶モニターにDell U2713HM使っています。

次期モデルが出るかもしれないのにMac miniを買って、自分でメモリを16Gに …