読者です 読者をやめる 読者になる 読者になる

久保清隆のブログ

ライフハック、健康、旅行、ビジネス、広告など、役に立つような情報を書きます。

セッションについて理解する 〜プログラミング基礎の基礎

Ruby/Rails

セッションを使うと、ユーザーが画面遷移してもユーザー特有の情報を失わないようにできる。

  • 現在のセッション情報を得る

→sessionメソッドを使う

session #=> #<CGI::Session:0x40a1df48...
  • セッションIDを取得する

→session_idメソッドを使う

session.session_id #=> "f1174c1766ejifjojpsjifjojgbiojsj"
  • セッションにデータを保存する
session[:user_id] = @user.id

違うページでユーザーデータを取得するには、

@user = User.find(session[:user_id])
  • Rails1.2まではセッションデータはサーバ側に保持、クッキー内のセッションIDをもとに、セッションデータを復元
  • Rails2.0からはセッションデータ全体がクッキーに保存。

⇒クッキー内のデータの改竄防止機構はあるが、ユーザからセッションデータの中身を見られる。
⇒・ユーザに見せてはいけないデータはセッションに入れてはならない。
 ・クッキーに保存されるため、大きなデータをセッションには入れられない。

  • セッションにデータを保存すると、保存対象のオブジェクトはObject#marshalメソッドシリアライズされて保存される。

⇒IOオブジェクトやProcオブジェクトなど、シリアライズできないオブジェクトはセッションに格納することが出来ない。
シリアライズ:ソフトウェア内部で扱っているデータを丸ごと、ファイルで保存したりネットワークで送受信することができるように変換すること。逆に、シリアライズされたデータをソフトウェアが扱えるデータに変換することをデシリアライズという。

  • デフォルト値付きHashはマーシャルできない

※マーシャル:obj を再帰的にファイルに書き出すこと。(ファイルに書き出せないオブジェクトをファイルに書き出そうとすると例外 TypeError が発生)。

  • セッションの保存方法を変更する

ActiveRecordを使ってセッション情報をDBに保存する

普通このセッション情報は、ユーザのクッキーの値とサーバのセッション情報の値が同じものをつきあわせて、サーバのセッション情報を使う。
ではサーバにはどうやってセッション情報が保存されているかというと、デフォルトではファイルで保存されている。
それをファイルではなくてDBに保存するには、rakeを使う。
コマンドプロンプトで、

 rake db:sessions:create

これで、セッション情報テーブルを作成するためのマイグレーションファイルを生成。

続けて、

  rake db:migrate #実行してテーブルを作成

で実行してテーブルを作成。

その後、設定ファイルconfig/environment.rbにセッション管理方法を指定する。
セッションの保存方法を変更するには、ActionController::Baseのクラスメソッド、session_store=(store)を使用。

ActiveRecordを使うには、:active_record_storeを指定。

config.action_controller.session_store = :active_record_store


実際にやってみると、migrationファイルができた。

    > rake db:sessions:create
    (in /home/roruser/myApplication)
    exists db/migrate
    create db/migrate/001_add_sessions.rb


ファイルの中を見てみる。これは、sessionsテーブルを作るためのmigrationファイル。

class AddSessions < ActiveRecord::Migration
  def self.up
    create_table :sessions do |t|
      t.column :session_id, :string
      t.column :data, :text
      t.column :updated_at, :datetime
    end

    add_index :sessions, :session_id
    add_index :sessions, :updated_at
  end

  def self.down
    drop_table :sessions
  end
end


では、実際にmigrateする。

> rake db:migrate
(in /home/roruser/myApplication)
== AddSessions: migrating =====================================================
-- create_table(:sessions)
-> 0.3056s
-- add_index(:sessions, :session_id)
-> 0.2372s
-- add_index(:sessions, :updated_at)
-> 0.0926s
== AddSessions: migrated (0.6439s) ============================================

どんなsessionsテーブルができたかというと、

    $mysql explain sessions;
    +------------+--------------+------+-----+---------+----------------+
    | Field      | Type         | Null | Key | Default | Extra          |
    +------------+--------------+------+-----+---------+----------------+
    | id         | int(11)      | NO   | PRI | NULL    | auto_increment | 
    | session_id | varchar(255) | YES  | MUL | NULL    |                | 
    | data       | text         | YES  |     | NULL    |                | 
    | updated_at | datetime     | YES  | MUL | NULL    |                | 
    +------------+--------------+------+-----+---------+----------------+
    4 rows in set (0.01 sec)


最後に、config/environment.rb ファイルを変更。

# Use the database for sessions instead of the file system
# (create the session table with 'rake db:sessions:create')
# config.action_controller.session_store = :active_record_store

という箇所で、最後の行のコメントをはずす。

# Use the database for sessions instead of the file system
# (create the session table with 'rake db:sessions:create')
config.action_controller.session_store = :active_record_store


後は、Webサーバを再起動すれば、セッション変数を使ったとき(たとえば、 session[:hoge] のように)は、DBにセッション情報が保存されるようになる。


→その他のセッション情報保存方法
 ・DRbStore:DRbによる分散オブジェクト環境を利用したもの。
 ・MemCacheStore:memcachedをストレージとして利用するもの。
 ・SqlSessionStore:ActiveRecordを使わず、直接SQLを実行するもので、ActiveRecordStoreより高速。
  プラグインとしてインストールできる。

  • セッションを無効にする

→reset_sessionメソッドを使用。

def login
  reset_session
  ...
end
  • セッションデータを削除する

ActiveRecord形式のセッション情報を削除する場合

 ruby script/runner 'CGI::Session::ActiveRecordStore::Session. delete_all(["sessions.updated_at < ?", 3.days.ago])'

※script/runnerはRails環境を読み込んだ上でワンライナーを実行するためのスクリプト
これをcronで定期的に実行すると、セッションデータが溜まらずにすむ。


ちなみに、
rails を動かしていて、セッションに入っている情報を一旦クリアしないと、プログラムが動かない状況になった場合には、コマンドプロンプトで、

> rake db:sessions:clear

と打てば、サーバのセッション情報がオールクリアされる。
(ファイル管理でも、DB管理でも。)


────────────────────────


twitter@kbkt:IT系の最新情報やライフハック情報についてのつぶやき。
久保清隆 facebook
Add to Google Subscribe with livedoor Reader
にほんブログ村 サラリーマン日記ブログ 戦うサラリーマンへ 人気ブログランキングへ


◆◆このブログのサイトマップへ◆◆