セッション/クッキーなど

Railsの状態管理の方法は、いわゆるセッションやクッキーのほか、フラッシュってのもあるみたい。

クッキーは、cookiesメソッドで!

  • 一番簡単に書くと、こんな感じ
    • コントローラ(controllers/ctrl_controller.rb)は、こう書いて、
       def cookie
         @data = cookies[:data]
       end
       def cookie_regist
         cookies[:data] = params[:data]
         render :text => 'クッキーを保存しました'
       end
      
    • テンプレート(views/ctrl/cookie.html.erb)は、こう書けば
      <%= form_tag( { :action => 'cookie_regist'} ) do %>
        <label>クッキー登録データ
          <%= text_field_tag 'data', @data, { :size => 50 }%></label>
        <%= submit_tag('保存') %>
      <% end %>
      
    • http://localhost:3000/ctrl/cookie にアクセスすれば、前回のクッキーの保存した値が出る、と。
  • 実際には、expiresとかも指定するんで、こんな感じかな?
     def cookie_regist
       cookies[:data] = { :value => params[:data],
                          :expires => 3.months.from_now, # こういう書き方、イカスな!
                          :http_only => true             # HTTPのみにすることで、JavaScriptでのクッキーアクセスが遮断されるらしい
                        }
       render :text => 'クッキーを保存しました'
     end
    
    • ちゃんとしたサイトなら、:domainと:pathは指定すないとまずいよな
    • :secureをtrueにしたら、暗号化してるときのみクッキーを送信するから、安心!
  • クッキーの削除は、cookies.delete()でね。
    • cookie_registの初めにこんなのを追加して、
         if params[:delete] 
           cookies.delete(:data)
           render :text => 'クッキーを削除しました' and return
         end
      
    • テンプレートにこれを追加して、削除ボタンでクッキーを削除できるよ
        <%= submit_tag('削除', {:name => :delete}) %>
      
      • あー、:domain、:pathを指定してある時は、delete時にも指定しないと駄目みたいなんで、注意!
  • Rails3だと、永続化や署名もできるんだ!
    • 永続化はこうね
      cookies.permanent[:data] = { :value => 'でーた',
      
      • 永続化って、有効期限が20年に設定されてるクッキーで、この場合は:expire指定も無視されるみたい
    • 署名のほうは、こう
      cookies.signed[:data] = { :value => 'でーた',
      
      • 一緒にも書けるんだ!
        cookies.permanent.signed[:data] = { :value => 'でーた',
        
      • ちなみに、署名のトークンは「config/initializers/secret_token.rb」で、Railbook::Application.config.secret_token として定義されてるみたい。

セッションは、sessionメソッドで!

  • Railsのセッションは、3種類のデータストアがあるだー。
    保存先 説明 上限
    クッキー クッキーね。デフォルトは、コレ。 4KB
    データベース RDBね。ActiveRecord経由で保存 DB次第
    Memcached 汎用の分散型メモリキャッシュシステムね。 1MB
    • 当たり前だけど、セッションIDだけは常にクッキー経由ね。
      • 今時、クッキーとかJavaScriptがNGのサイトなぞ、あり得ないって、コンセプトなんだねw。まああり得ないとは思うけどさ。
  • で、セッションの使い方はこんな感じで、cookiesとほとんど一緒。
    • コントローラ側は、こう
       def session_show
         @data = session[:data]
       end
       def session_regist
         session[:data] = params[:data]
         render :text => 'セッションを保存しました'
       end
      
    • テンプレートは、こう
      <%= form_tag( { :action => 'session_regist'} ) do %>
        <label>セッション登録データ
          <%= text_field_tag 'data', @data, { :size => 50 }%></label><br>
        <%= submit_tag('保存') %>
      <% end %>
      
    • まあ、これだけだと保存先はデフォルトのクッキーなので、ブラウザを閉じると消えちゃう状態ね。
    • あ、セッションのクリアは、nilを設定ね!
      sesseion[:data] = nil # キーでクリア
      reset_session         # 全てのセッションをクリア
      
  • んでもって、簡単にやるなら、こんなセッションの設定をすればDBにセッションが保存される、と。
    • まずは、セッションのコンフィグ(config/initializers/session_store.rb)に、以下のようにActiveRecordを設定して、Webサーバを再起動!
      Railbook::Application.config.session_store :active_record_store
      Railbook::Application.config.session_store = {
        :key => '_railbook_session',
        :httponly => true,
        :expire_after => 2.weeks
      }
      
    • セッションのデータベースを準備するため、以下のコマンドを実行
      rake db:sessions:create
      rake db:migrate
      
      • これで、以下のようなカラムの[sessions]テーブルが生成されるはず(無論、この他、idとかもある)
        カラム名 データ型 DBの型(sqlite)
        session_id string varchar(255) NOT NULL
        data text text
    • で、セッション管理してる画面を叩けば、このsessionsテーブルにデータが入る、と。
    • んー、セッション管理はできてるけど、ブラウザ閉じたらセッション消えちゃうのはなぜ?:expire_afterを指定してるのに?
      • あー、判った。_session_idが永続化されてないからか!そりゃそうだ。
      • ただ、さすがにセッションIDは永続化すべきじゃないし、その辺はまた別途かなー。
    • ちなみに、セッションの削除はこんな感じで!
      session[:data] = nil # dataのセッションを削除する
      reset_session        # 全て削除
      
  • で、当然、セッションクリアしない場合は、DBにデータが残っちゃうから、別途削除する必要あり
    • そのまま、SQLでDELETE文でも実行できるだろうけど、こんなActiveRecordを叩いてもOK
      rails runner -e development "ActiveRecord::SessionStore::Session.delete_all([ 'updated_at < ?', 1.day.ago ])"
      
      • この場合は、development環境用ね。

フラッシュは、リダイレクト時の完了画面のメッセージ用だね!

  • 要するに、次のリクエストでのみデータを渡せる特殊なセッションですかな?
    • あー、既にScaffoldingの登録や更新系でやってた奴なんだ!
    • 基本は、コントローラ側でこんな感じで書いて、
      format.html { redirect_to @book, notice: 'Book was successfully created.' }
      
    • ビュー側では、こんな感じで書けばOKね!
      <p id="notice"><%= notice %></p>
      
  • redirect_toのパラメータとして、:noticeを渡せば、次の画面でだけ取れる、と。良くできてるなー。
    • あ、:alertでもOKみたい!
  • でも、このredirect_toでの指定って、Rails3からのみなのか。
    • なんで、こんな感じで、flashメソッドで書くのもあり
      format.html { 
        flash[msg] = 'Book was successfully created.' 
        redirect_to @book
      }
      
    • ビュー側は、こうね
      <p id="notice"><%= flash[:msg] %></p>
      
      • ふーん。noticeやalertはローカル変数としてアクセスできるけど、その他はflashメソッド経由なんだねー

-
最終更新:2012年01月13日 07:27