Skip to content
Browse files

Merge pull request #342 from brainopia/e5b4d961e5cb310bffca18a2cf72a1…

…1b1075f8bd

Rack::Session remove inheritance from Hash
  • Loading branch information...
2 parents c4fc616 + a826b46 commit 75b358c67504978276bceff452dfb74d279391a6 @raggi raggi committed
Showing with 45 additions and 49 deletions.
  1. +45 −49 lib/rack/session/abstract/id.rb
View
94 lib/rack/session/abstract/id.rb
@@ -18,89 +18,85 @@ module Abstract
ENV_SESSION_KEY = 'rack.session'.freeze
ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
- # Thin wrapper around Hash that allows us to lazily load session id into session_options.
+ # SessionHash is responsible to lazily load the session from store.
+
+ class SessionHash
+ include Enumerable
+ attr_writer :id
- class OptionsHash < Hash #:nodoc:
- def initialize(by, env, default_options)
+ def initialize(by, env)
@by = by
@env = env
- @session_id_loaded = false
- merge!(default_options)
- end
-
- def [](key)
- load_session_id! if key == :id && session_id_not_loaded?
- super
+ @loaded = false
end
- private
-
- def session_id_not_loaded?
- !(@session_id_loaded || key?(:id))
+ def id
+ return @id if @loaded or instance_variable_defined?(:@id)
+ @id = @by.send(:extract_session_id, @env)
end
- def load_session_id!
- self[:id] = @by.send(:extract_session_id, @env)
- @session_id_loaded = true
+ def options
+ @env[ENV_SESSION_OPTIONS_KEY]
end
- end
- # SessionHash is responsible to lazily load the session from store.
-
- class SessionHash < Hash
- def initialize(by, env)
- super()
- @by = by
- @env = env
- @loaded = false
+ def each(&block)
+ load_for_read!
+ @data.each(&block)
end
def [](key)
load_for_read!
- super(key.to_s)
+ @data[key.to_s]
end
+ alias :fetch :[]
def has_key?(key)
load_for_read!
- super(key.to_s)
+ @data.has_key?(key.to_s)
end
alias :key? :has_key?
alias :include? :has_key?
def []=(key, value)
load_for_write!
- super(key.to_s, value)
+ @data[key.to_s] = value
end
+ alias :store :[]=
def clear
load_for_write!
- super
+ @data.clear
end
def destroy
- clear
- options = @env[ENV_SESSION_OPTIONS_KEY]
- options[:id] = @by.send(:destroy_session, @env, options[:id], options)
+ clear
+ @id = @by.send(:destroy_session, @env, id, options)
end
def to_hash
load_for_read!
- Hash[self].delete_if { |k,v| v.nil? }
+ @data.dup
end
def update(hash)
load_for_write!
- super(stringify_keys(hash))
+ @data.update(stringify_keys(hash))
+ end
+ alias :merge! :update
+
+ def replace(hash)
+ load_for_write!
+ @data.replace(stringify_keys(hash))
end
def delete(key)
load_for_write!
- super(key.to_s)
+ @data.delete(key.to_s)
end
def inspect
if loaded?
- super
+ @data.inspect
else
"#<#{self.class}:0x#{self.object_id.to_s(16)} not yet loaded>"
end
@@ -108,6 +104,7 @@ def inspect
def exists?
return @exists if instance_variable_defined?(:@exists)
+ @data = {}
@exists = @by.send(:session_exists?, @env)
end
@@ -117,7 +114,7 @@ def loaded?
def empty?
load_for_read!
- super
+ @data.empty?
end
def merge!(hash)
@@ -136,9 +133,8 @@ def load_for_write!
end
def load!
- id, session = @by.send(:load_session, @env)
- @env[ENV_SESSION_OPTIONS_KEY][:id] = id
- replace(stringify_keys(session))
+ @id, session = @by.send(:load_session, @env)
+ @data = stringify_keys(session)
@loaded = true
end
@@ -243,7 +239,7 @@ def generate_sid(secure = @sid_secure)
def prepare_session(env)
session_was = env[ENV_SESSION_KEY]
env[ENV_SESSION_KEY] = SessionHash.new(self, env)
- env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
+ env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup
env[ENV_SESSION_KEY].merge! session_was if session_was
end
@@ -268,7 +264,7 @@ def extract_session_id(env)
# Returns the current session id from the OptionsHash.
def current_session_id(env)
- env[ENV_SESSION_OPTIONS_KEY][:id]
+ env[ENV_SESSION_KEY].id
end
# Check if the session exists or not.
@@ -314,21 +310,21 @@ def security_matches?(env, options)
# response with the session's id.
def commit_session(env, status, headers, body)
- session = env['rack.session']
- options = env['rack.session.options']
+ session = env[ENV_SESSION_KEY]
+ options = session.options
if options[:drop] || options[:renew]
- session_id = destroy_session(env, options[:id] || generate_sid, options)
+ session_id = destroy_session(env, session.id || generate_sid, options)
return [status, headers, body] unless session_id
end
return [status, headers, body] unless commit_session?(env, session, options)
session.send(:load!) unless loaded_session?(session)
- session = session.to_hash
- session_id ||= options[:id] || generate_sid
+ session_id ||= session.id || generate_sid
+ session_data = session.to_hash.delete_if { |k,v| v.nil? }
- if not data = set_session(env, session_id, session, options)
+ if not data = set_session(env, session_id, session_data, options)
env["rack.errors"].puts("Warning! #{self.class.name} failed to save session. Content dropped.")
elsif options[:defer] and not options[:renew]
env["rack.errors"].puts("Defering cookie for #{session_id}") if $VERBOSE

0 comments on commit 75b358c

Please sign in to comment.
Something went wrong with that request. Please try again.