Railsで作る最も簡単なブログシステム(4)

Railsで作る最も簡単なブログシステム(3) - dan5yaの日記の続きです。

記事の編集と閲覧は可能になりました。しかしまだ重大な仕事が残っています。認証です。

今のままだと誰でも記事を編集できてしまいます。認証機能を追加してオーナー以外には記事の編集ができないようにします。

認証が必要なページ

あとで書く。

acts_as_authenticatedプラグインで認証

認証機能を実現するためにacts_as_authenticatedプラグインを使用します。

次のコマンドで、acts_as_authenticatedプラグインをプロジェクトにインストールすることができます。

ruby script/plugin source http://svn.techno-weenie.net/projects/plugins
ruby script/plugin install acts_as_authenticated

上記コマンドによりacts_as_authenticatedプラグインがダウンロードされ、vendor/plugins/ディレクトリ以下に必要なファイルがコピーされます。

プロジェクトにacts_as_authenticatedプラグインがインストールされると、認証に必要な各種ファイルをジェネレートできるようになります。次のコマンドを実行してください。

ruby script/generate authenticated User

上記コマンドにより、認証に必要なモデル、コントローラ、ビューが生成されます。

Migration定義ファイルも生成されます。次のコマンドで実行してください。

rake db:migrate

ユーザー情報を記録するusersテーブルがDBに作成されます。

app/controllers/application.rbをエディタで開いて、ApplicationControllerクラス定義の先頭に次の1行を追加してください。

class ApplicationController < ActionController::Base
  include AuthenticatedSystem      # ←追加
  (略)

これですべてのコントローラに対して認証処理を行うAuthenticatedSystemモジュールの機能が追加されます。
また、app/controllers/entries_controller.rbをエディタで開いて、EntriesControllerクラス定義の先頭に次の1行を追加してください。

class EntriesController < ApplicationController
  before_filter :login_required    # ←追加
  (略)

これでEntriesのアクションはログインした状態でないとアクセス出来なくなります。

上記のようにapplication.rbとentries_controller.rbを書き換えた後、ブラウザから管理画面(http://localhost:3000/entries)を開いてみてください。するとログイン画面に飛ばされるはずです。今はまだログインしていませんから、管理ページを開くことができずに、ログインページへのリダイレクト(強制ジャンプ)が発生したわけです。

ログインするにはサインアップを行う必要があります。ブラウザでhttp://localhost:3000/users/signupを開いてください。すると次のようなページが開きます。

TODO.SS

各項目を入力し、サインアップを行ってください。無事サインアップが完了するとユーザー情報はDBに登録されます。
サインアップ直後は自動的にログインした状態になるので、管理画面(http://localhost:3000/entries)を開くことができるようになります。

トップメニューの「ログアウト」をクリックするとUsersコントローラのlogoutアクションが呼び出されて、ログアウトが行われます。ログアウト後に管理画面を開くには、もう一度ログイン(http://localhost:3000/users/login)が必要です。


このままだと誰でもサインアップできてしまうので、Usersコントローラを書き換えます。signupメソッドの先頭に次の1行を追加して、1人しかサインアップできないようにしてしまいます。

app/controllers/users_controller.rb

class UsersController < ApplicationController
  (略)

  def signup
      redirect_to(:action => 'login') if User.count > 0
      (略)

ブラウザからサインアップページ(http://localhost:3000/users/signup)を開いてみてください。ログインページへリダイレクトするはずです。これでもう新しいユーザーがサインアップすることはできません。

トップメニューを修正する

ログアウトした状態でトップページ(http://localhost:3000/home)を開いてみてください。ログインしていないのに「日記を書く」「管理」「ログアウト」といったメニューが表示されています。これらはログインしたユーザーにだけ見えればいいものです。これらのメニューがログインしていないユーザーから見えないように修正しましょう。

トップメニューはレイアウトのビューに記述されています。

app/views/layouts/application.html.erb

  (略)
  <%= link_to '日記を書く', :controller => 'entries', :action => 'new' %>
  <%= link_to '管理', :controller => 'entries', :action => '' %>
  <%= link_to 'ログアウト', :controller => 'users', :action => 'logout' %>
</div>
(略)

上記の部分を次のように修正します。

  (略)
  <% if logged_in? %>
    <%= link_to '日記を書く', :controller => 'entries', :action => 'new' %>
    <%= link_to '管理', :controller => 'entries', :action => '' %>
    <%= link_to 'ログアウト', :controller => 'users', :action => 'logout' %>
  <% else %>
    <%= link_to 'ログイン', :controller => 'users', :action => 'login' %>
  <% end %>
</div>
(略)

logged_in?というのはログイン中であるかどうかを調べるメソッドです。ログイン中であれば、管理者に必要なリンクを表示し、ログインしていなければログインページへのリンクだけを表示するようにしました。

showアクションに対する認証解除

Entriesコントローラのshowアクションの認証を外します。

app/controllers/entries_controller.rb

class EntriesController < ApplicationController
  before_filter :login_required, :except => [:show]
  (略)

ちなみに、:exceptの代わりに:onlyを指定すると特定のアクションのみに認証をかけることができます。

  before_filter :login_required, :only => [:index, :update] 

上の例では、indexアクションとupdateアクションに認証がかかります。

またこのページ下部に表示されているリンクは管理者用のページに対するリンクなので、非ログインジは表示しないようにしておきます。

app/views/entries/show.html.erb

<% if logged_in? %>
  <%= link_to 'Edit', edit_entry_path(@entry) %> |
  <%= link_to 'Back', entries_path %>
<% end %>

上のようにリンクを生成する部分をif文で囲んでおきます。

トップページ表示される記事を5件に制限する

app/controllers/home_controller.rb

class HomeController < ApplicationController

  def index
     @entries = Entry.find(:all, :order => "created_at DESC", :limit => 5)
  end
  (略)

Entry.fildメソッドの引数に「:limit => 5」を追加します。これで最新の5件の記事が@entriesに代入されます。記事の総数が5件よりも少ない場合は、すべての記事が@entriesに代入されます。

まとめ

  • acts_as_authenticatedをインストール
  • テーブルを作成
    • rake db:migrate
  • 認証チェックを追加
    • app/controllers/application.rb に「include AuthenticatedSystem」を追加
    • app/controllers/entries_controller.rb に「before_filter :login_required」を追加
    • app/controllers/users_controller.rb を修正してサインアップを1ユーザーに限定
    • app/views/layouts/application.html.erb を修正(トップメニューの修正)
  • showアクションに対する認証解除
    • app/controllers/entries_controller.rb → before_filter :login_required, :except => [:show]
  • 記事を5件
    • app/controllers/home_controller.rb → @entries = Entry.find(:all, :order => "created_at DESC", :limit => 5)

Railsで作る最も簡単なブログシステム(5) - dan5yaの日記に続きます。