`
hideto
  • 浏览: 2666279 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Rails源码研究之ActionController:四,session

    博客分类:
  • Ruby
阅读更多
我们知道Rails默认使用file来存储session数据,放在tmp\sessions目录下
其实我们还可以使用数据库、drb_server、mem_cache甚至内存来存储session数据
方法就是更改environment.rb:
config.action_controller.session_store = :active_record_store || :drb_store || :mem_cache_store || :memory_store

当然使用数据库存储session数据时要先创建数据库表
rake db:sessions:create

这在以前的Rails良药系列文章中也提到了

Rails的session管理的源代码文件为session_management.rb:
require 'action_controller/session/drb_store'
require 'action_controller/session/mem_cache_store'
if Object.const_defined?(:ActiveRecord)
  require 'action_controller/session/active_record_store'
end

module ActionController
  module SessionManagement

    def self.included(base)
      base.extend(ClassMethods)
      base.send :alias_method_chain, :process, :session_management_support
      base.send :alias_method_chain, :process_cleanup, :session_management_support
    end

    module ClassMethods
      def session_store=(store)
        ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager] =
          store.is_a?(Symbol) ? CGI::Session.const_get(store == :drb_store ? "DRbStore" : store.to_s.camelize) : store
      end
      def session_store
        ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager]
      end
      def session_options
        ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS
      end
      def session(*args)
        options = Hash === args.last ? args.pop : {}
        options[:disabled] = true if !args.empty?
        options[: only] = [*options[: only]].map { |o| o.to_s } if options[: only]
        options[:except] = [*options[:except]].map { |o| o.to_s } if options[:except]
        if options[: only] && options[:except]
          raise ArgumentError, "only one of either : only or :except are allowed"
        end

        write_inheritable_array("session_options", [options])
      end
      def session_options_for(request, action) #:nodoc:
        if (session_options = cached_session_options).empty?
          {}
        else
          options = {}

          action = action.to_s
          session_options.each do |opts|
            next if opts[:if] && !opts[:if].call(request)
            if opts[: only] && opts[: only].include?(action)
              options.merge!(opts)
            elsif opts[:except] && !opts[:except].include?(action)
              options.merge!(opts)
            elsif !opts[: only] && !opts[:except]
              options.merge!(opts)
            end
          end
          
          if options.empty? then options
          else
            options.delete : only
            options.delete :except
            options.delete :if
            options[:disabled] ? false : options
          end
        end
      end
    end

    def process_with_session_management_support(request, response, method = :perform_action, *arguments) #:nodoc:
      set_session_options(request)
      process_without_session_management_support(request, response, method, *arguments)
    end

    private

      def set_session_options(request)
        request.session_options = self.class.session_options_for(request, request.parameters["action"] || "index")
      end
      def process_cleanup_with_session_management_support
        clear_persistent_model_associations
        process_cleanup_without_session_management_support
      end
      def clear_persistent_model_associations #:doc:
        if defined?(@_session) && @_session.respond_to?(:data)
          session_data = @_session.data

          if session_data && session_data.respond_to?(:each_value)
            session_data.each_value do |obj|
              obj.clear_association_cache if obj.respond_to?(:clear_association_cache)
            end
          end
        end
      end
  end
end

alias_method_chain对process和process_cleanup方法加上session_management_support
我们在看action_controller/base.rb文件时知道process方法是action调用的入口,而process_cleanup是action调用结束时调用的
而@_session变量也是在base.rb里定义的:
@_response = response
@_response.session = request.session
@_session = @_response.session


我们可以在controller里调用session这个类方法来指定使用session的范围:
# turn off session management for all actions.
session : off

# turn off session management for all actions _except_ foo and bar.
session : off, :except => %w(foo bar)

# turn off session management for only the foo and bar actions.
session : off, : only => %w(foo bar)

# the session will only work over HTTPS, but only for the foo action
session : only => :foo, :session_secure => true

# the session will only be disabled for 'foo', and only if it is requested as a web service
session : off, : only => :foo,
  :if => Proc.new { |req| req.parameters[:ws] }


看看active_record_store.rb中的一段代码:
class CGI
  class Session
    class ActiveRecordStore

      class Session < ActiveRecord::Base
        cattr_accessor :data_column_name
        self.data_column_name = 'data'

        class << self
          def create_table!
            connection.execute <<-end_sql
              CREATE TABLE #{table_name} (
                id INTEGER PRIMARY KEY,
                #{connection.quote_column_name('session_id')} TEXT UNIQUE,
                #{connection.quote_column_name(@@data_column_name)} TEXT(255)
              )
            end_sql
          end
          def drop_table!
            connection.execute "DROP TABLE #{table_name}"
          end
        end
      end

      cattr_accessor :session_class
      self.session_class = Session

      def initialize(session, option = nil)
        session_id = session.session_id
        unless @session = ActiveRecord::Base.silence { @@session_class.find_by_session_id(session_id) }
          unless session.new_session
            raise CGI::Session::NoSession, 'uninitialized session'
          end
          @session = @@session_class.new(:session_id => session_id, :data => {})
        end
      end

      def update
        if @session
          ActiveRecord::Base.silence { @session.save }
        end
      end

      def close
        if @session
          update
          @session = nil
        end
      end

      def delete
        if @session
          ActiveRecord::Base.silence { @session.destroy }
          @session = nil
        end
      end

    end
  end
end

active_record_store是使用数据库保存session,里面定义了create_table!方法以及update/delete/close等与数据库@session相关的操作
而mem_cache_store的update/delete/close等方法的实现则是对@cache的操作,drb_store则是对DRbObject的操作,不同的方式有不同的实现
分享到:
评论

相关推荐

    Rails的精简版本Rails::API.zip

    Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails 应用程序要快。 Rails::API 可以用来创建只提供API服务(API-Only)的 Rails ...

    Rails进行敏捷Web开发(所有版本的源码rails3.0-4.0)

    1. Rails 3.0: Rails 3是重大升级,引入了ActionController::Metal,这是一个轻量级的控制器,用于提高性能。同时,它引入了多路由引擎支持,如Rack中间件,使得与其他Web服务器的集成更加容易。此外,ActiveRecord...

    live-stream:Rails 4 ActionController Live Stream 演示简单的聊天应用程序

    使用 Rails 4 的简单聊天应用程序 - ActionController::Live 应用组件: 1 . 使用 Rails 4 ActionController::Live 的聊天应用程序 2 . 基本 LDAP 身份验证 3 . Redis 服务器集成 4 . 彪马服务器 1 . Rails 4 ...

    Rails中应用Ext.tree:以中国的省市地区三级联动选择为例

    在Ruby on Rails(Rails)框架中,开发人员经常需要实现各种用户交互功能,例如三级联动选择,这在处理如中国省市区这样的地理数据时尤其常见。这篇博客文章“Rails中应用Ext.tree:以中国的省市地区三级联动选择为...

    rails-exporter-源码.rar

    《Rails Exporter 源码解析》 Rails Exporter 是一个用于 Rails 应用程序的开源工具,主要用于数据导出功能。源码分析将帮助我们深入理解其内部工作原理,以便更好地利用它来优化我们的应用。 一、Rails 框架基础 ...

    Rails项目源代码

    这个Rails项目提供了学习和研究Web开发的机会,特别是对于Ruby on Rails新手,可以通过阅读和理解源代码来提升技能,了解实际应用中Rails的用法。同时,对于有经验的开发者,这个项目也可以作为一个起点,进行二次...

    ruby on rails 教程源码

    Ruby on Rails,简称Rails,是基于Ruby语言的开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,旨在使开发过程更加简洁高效。这个“ruby on rails 教程源码”很可能是为了辅助学习者深入理解Rails的...

    rails-session_cookie:一个用于获取原始Rails会话Cookie的机架应用

    Rails :: SessionCookie 快速,松散耦合的请求有关经过Cookie验证的应用程序的规范。 为什么 可能,您可能已经看到了很多像这样的代码: # config/initializers/session_store.rb Rails . application . config . ...

    Rails 3 in Action

    《Rails 3 in Action》是2011年由Ryan Bigg撰写的一本关于Ruby on Rails框架的权威指南,专门针对当时最新的Rails 3.1版本进行了深入解析。这本书旨在帮助开发者充分利用Rails 3.1的强大功能,提升Web应用开发的效率...

    Agile Web Development with Rails 4th edition(敏捷Web开发与Rails:程序指南 第四版)

    《敏捷Web开发与Rails:程序指南 第四版》是一本深度探讨使用Ruby on Rails框架进行敏捷Web应用开发的专业书籍。本书旨在帮助开发者充分利用Rails 4的特性,提高开发效率,实现快速迭代和高质量的代码编写。 Rails是...

    Web开发敏捷之道--应用Rails进行敏捷Web开发 之 Depot代码。

    标题中的“Web开发敏捷之道--应用Rails进行敏捷Web开发 之 Depot代码”表明这是一个关于使用Ruby on Rails框架进行敏捷Web开发的示例项目,名为Depot。Ruby on Rails(简称Rails)是一个开源的Web应用程序框架,它...

    rails-controller-testing:将`assigns`和`assert_template`带回到您的Rails测试中

    Rails :: Controller :: Testing 这个gem将assigns给控制器测试的内容以及assert_template带回assigns控制器和集成测试的内容。 这些方法已中。 安装 将此行添加到您的应用程序的Gemfile中: gem 'rails-...

    《Ruby On Rails》 源码 下载、导入、运行

    本书源码 博文链接:https://msnvip.iteye.com/blog/139752

    bhl_rails_solr-源码.rar

    《深入解析bhl_rails_solr源码》 在当今的Web开发领域,Rails框架以其高效、简洁的设计理念,深受开发者喜爱。同时,Solr作为一款强大的全文搜索引擎,被广泛应用于各类复杂的数据检索场景。当这两者结合时,便诞生...

    基于ruby on rails开发示例源码

    Rails的许多特性,如ActiveRecord(ORM)、ActiveModel、ActionController和ActionView,都是为了支持这种分层架构。 压缩包中的`seanatnci-rails_space-53c56b4`可能是一个具体的Rails项目仓库,包含以下关键组成...

    ruby on rails社区网站开发源码

    通过研究这个源码,你可以深入理解Rails的工作原理,学习如何设计和实现社区网站的核心功能,如用户注册、论坛讨论、个人资料管理等。同时,这也是一个绝佳的机会去实践敏捷开发和TDD(测试驱动开发)原则,提升你的...

    Rails相关电子书汇总

    2. **ActionController**:负责处理HTTP请求,并将数据转发给相应的模型和视图。它管理着应用的业务逻辑和控制流程。 3. **ActionView**:负责生成HTML或其他类型的响应,通常与模板系统一起工作,将数据以用户友好...

    Rails 4 in Action, Second Edition.pdf

    为了帮助读者更好地理解和应用所学知识,**Rails 4 in Action, 第二版** 包含了一系列案例研究和实战项目,例如: - **电子商务网站开发**:从零开始构建一个完整的电子商务平台,涵盖商品管理、订单处理等功能。 -...

Global site tag (gtag.js) - Google Analytics