[Rails]acts_as_authenticatedを使う

ログイン、認証周りの処理を作成するのに使えるかと思い調べてみた。

インストール

インストール等については、以下を参照した。

プラグインインストール後、認証に対応したモデルとコントローラを生成する。

$ ruby script/generate authenticated MODEL CONTROLLER

概要

上記手順を実行すると、以下のファイルが生成される。

  • app/models/user.rb
  • app/controllers/account_controller.rb
  • app/views/account/index.rhtml
  • app/views/account/login.rhtml
  • app/views/account/signup.rhtml
  • lib/authenticated_system.rb

できそうなことは、大体以下のような感じ。

  • サインアップフォームによるユーザ登録
  • ログイン処理
  • ログアウト処理
  • 非ログイン時のアクション実行禁止

カスタマイズ

とりあえず今回はサインアップの機能は入らないのでごっそり削除したのと、自前で用意したホーム画面を表示したいので、Controllerのあたりをゴリゴリ書き換えた。
また、自前のホーム画面を表示するためにhomeアクションを追加している。いろいろ弄った結果、こんな形になった。

class AccountController < ApplicationController
  # Be sure to include AuthenticationSystem in Application Controller instead
  include AuthenticatedSystem
  # If you want "remember me" functionality, add this before_filter to Application Controller
  before_filter :login_from_cookie

  # say something nice, you goof!  something sweet.
  def index
    if logged_in? then
      redirect_to(:action => 'home')
    else
      redirect_to(:action => 'login')
    end
  end

  def login
    redirect_to :action => 'home' if logged_in?
    return unless request.post?

    self.current_user = User.authenticate(params[:login], params[:password])
    if logged_in?
      if params[:remember_me] == "1"
        self.current_user.remember_me
        cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
      end
      flash[:notice] = "Logged in successfully"
      redirect_to :action => 'home'
    end
  end

  def home
    if logged_in? then
      @members = current_user.members
    else
      redirect_to :action => 'login' unless logged_in?
    end
  end

  def logout
    self.current_user.forget_me if logged_in?
    cookies.delete :auth_token
    reset_session
    flash[:notice] = "You have been logged out."
    redirect_to :action => 'login'
  end
end

非ログイン時のアクション実行禁止

Controller内に以下の記述をするだけ。非ログイン時にはaccountコントローラのloginアクションが実行されるみたい。

  include AuthenticatedSystem
  before_filter :login_required

ここら辺の動きの詳細は authenticated_system.rb 内の login_required -> access_denied メソッドを読めばわかる。

[日記]生活改善応援サイト『早起き生活』

昨日発見して気になっていたんだけど、登録してみました。
去年くらいからなるべく自炊するように心がけているのだが、夏の間はどうもやる気にならなくて、10月になったとたん涼しくなってきたので、早めに起きて朝食をとる生活を始めたところ。
起床時間をグラフにしてブログに貼り付けられるみたいなので、もう少し続いたら貼り付けてみようと思う。

そういえば、先日どこかのコラムで、「続かないものはブログにしてしまえ」という格言(?)があることを知ったが、その典型的なサービスですね、これは。
起床時間の記録をAPIにしてくれないかな。で、はてブのエントリ時刻を登録できるようになれば、このブログも続くのになぁ〜

[日記]mixiリニューアル記念

と、いうわけではないが(2日も遅れてるし)、mixiの日記を外部ブログ、こちらに設定してみました。技術ネタがほとんどになってしまうが、先に書いたとおり規則正しい生活をしようと思うところもあり、これからちょくちょく日記的なことも書いていこうと思います。
よろしくお願いします。

[trac]tracのRuntimeError

自宅サーバに導入しているtrac環境のリポジトリにアクセスすると、ときどき以下のような変なエラーを出す。

RuntimeError: instance.__dict__ not accessible in restricted mode

Subversionへのアクセスは問題無くできるので放置していたのだが、やはり気持ち悪いのでちょっと原因を調べてみようと思った。

と、思っていたら、以下のページにそのものずばりの解決策が公開されていた。

10分で解決。いや〜とりあえずググってみるもんだなぁ。


(追記:01:56) たった今エラーが再発してしまいました。対処前に比べるとかなり発生頻度が減ったようですが、後日調べることにしてみます...

(追記:9/25) 上記リンク解説中、「各サイトごとの」という記述を意識していませんでした。VirtualHost を2つ持っているので、追加し忘れたもう一方のファイルへも設定を追加しました。

[Rails]redMineのインストール

最近、Railsベースのプロジェクト管理ソフトとして話題になっているredMineをインストールしてみた。
以下、自宅の環境(Vine Linux)にインストールした履歴。

Ruby on Railsを使えるようにする

Ruby環境の整備

Railsベースなので、まずはRubyが動作する環境にする必要がある。
基本方針として、Vineのパッケージとして提供されているものについてはそちらを利用することにするので、以下のパッケージをインストールした。

irb                1.8.5-0v11.1
rbbr               0.5.1-0v11
rdoc               1.8.5-0v11.1
refe               0.8.0-0v11
ruby               1.8.5-0v11.1
ruby-devel         1.8.5-0v11.1
ruby-xmlparser     0.6.8-0v12
Ruby Gemsのインストール

RailsRubyにおけるパッケージマネージャであるGemsを使用してインストールするのが一般的なため、まずはGemsをインストールする。
1. 以下のURLからrubygems-0.9.2.tgzを入手
http://docs.rubygems.org
2. ソース解凍、インストール

# tar xvfz rubygems-0.9.2.tgz
# cd rubygems-0.9.2
# ruby setup.rb config
# ruby setup.rb setup
# ruby setup.rb install
Railsのインストール

Gemsがインストールできるれば後は簡単で、以下のコマンドを実行するだけ。

# gem install rails -y
PostgreSQLアダプタ

今回データベースとしてPostgreSQLを使用するので、アダプタをインストールする。

# gem install postgres -- --with-pgsql-lib-dir=/usr/lib/postgresql --with-pgsql-include-dir=/usr/include/pgsql

redMine本体のインストール

DB環境の作成

Postgres上にredMineが使用するDBユーザを作成。今回は以下の形で作成した。

表領域 : redmine_space
データベース : redmine_db
ユーザ : redmine
パスワード : redmine

次に、redMineが上記DBに接続できるようにする。解凍ディレクトリ下のconfig/database.yml.sample を database.yml にコピーし、以下のように書き換える。

adapter: postgresql
database: redmine_db
username: redmine
password: redmine

シェルプロンプトから以下のコマンドを実行し、テーブルの作成とデフォルトデータをロードする。途中、言語を聞かれるのでjaを選択。

# rake db:migrate RAILS_ENV=production
# rake load_default_data RAILS_ENV=production

上記準備ができれば、ruby script/server でredMineが起動する。
ブラウザから http://localhost:3000 にアクセスして動作確認。

某牛丼屋のキャンペーンで

「三杯めは100円!」などといっているが、「三杯も食えるか!」と思ったのは私だけ?
別にいっぺんに食べなくてもいいみたいでした。
だって松井がCMやってるからさぁ、普通に食べそうだもんあそこらへんの人は...

ORA-08177: このトランザクションのアクセスをシリアル化できません

Oracleトランザクション遮断レベルをSERIALIZABLEに設定すると、こんなエラーが発生することがある。今回、お客さまがマスタに1レコード追加したとたんに頻発するようになったらしい。
マニュアルによると、「このエラーが発生することを前提として」例外を捕捉しリトライするようなプログラムを書かなければいけないらしいけど、作ったの4年も前だしそんな知識なかったから、いたるところでSERIALIZABLE設定をしている。
今更そんな多くの箇所に手を入れるのも嫌だし、直近の対応として例外が発生しなくなるようにしなければいけないため、いろいろと情報を探っていたら、どうも次のような現象らしい。

Oracleは、データの記録を「データブロック」という単位で行っているが、あるレコードをどのデータブロックに割り当てるかはOracleの内部で処理されており、同じテーブルのデータだからといって同じデータブロックに割り当てられるとは限らない。逆に、全く違うテーブルのデータが同じデータブロックに割り当てられる可能性もある。
今回発生したエラーは、複数のスレッドがたまたま同時に同じデータブロックにアクセスしようとしたとき、シリアル性を保証できないために発生する例外のようだ。

Oracleのデータは、削除や追加するたびに違うデータブロックに割り当てられるので、対象データをいったん削除し、再度追加することで異なるデータブロックに再割り当てされ、競合は発生しなくなるのではないか?

ということで、お客さまにその旨連絡して、様子を見てもらうことにした。
結果がわかるのは明日以降だろうけど、これで解決できるのであればラッキー。

(追記 9/25) 本日お客様から呼び出されちゃいました orz... やはり上記手順は暫定対処でしかないので、本質的にはソース改修するしかないようです。