Permalink
Browse files

Remove SessionHash inheritance from Hash

Previous api provided by SessionHash was inconsistent. All methods
provided by Hash which were not rewritten in SessionHash were behaving
incorrectly when session was not loaded yet. For example, #replace, #each,
 #keep_if and many more. So by dropping Hash inheritance we provide
clean api with all methods working without regard to whether session was
loaded or not.
  • Loading branch information...
1 parent 098d583 commit e5b4d961e5cb310bffca18a2cf72a11b1075f8bd @brainopia brainopia committed Feb 18, 2012
Showing with 23 additions and 18 deletions.
  1. +23 −18 lib/rack/session/abstract/id.rb
@@ -20,20 +20,17 @@ module Abstract
# SessionHash is responsible to lazily load the session from store.
- class SessionHash < Hash
+ class SessionHash
attr_writer :id
def initialize(by, env)
- super()
@by = by
@env = env
@loaded = false
- @id_loaded = false
end
def id
- return @id if @loaded or @id_loaded
- @id_loaded = true
+ return @id if @loaded or instance_variable_defined?(:@id)
@id = @by.send(:extract_session_id, @env)
end
@@ -43,24 +40,26 @@ def options
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
@@ -70,29 +69,36 @@ def destroy
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
end
def exists?
return @exists if instance_variable_defined?(:@exists)
+ @data = {}
@exists = @by.send(:session_exists?, @env)
end
@@ -102,7 +108,7 @@ def loaded?
def empty?
load_for_read!
- super
+ @data.empty?
end
private
@@ -117,7 +123,7 @@ def load_for_write!
def load!
@id, session = @by.send(:load_session, @env)
- replace(stringify_keys(session))
+ @data = stringify_keys(session)
@loaded = true
end
@@ -297,7 +303,6 @@ def commit_session(env, status, headers, body)
options = session.options
if options[:drop] || options[:renew]
- # if there is no session.id then we have nothing to destroy?!
session_id = destroy_session(env, session.id || generate_sid, options)
return [status, headers, body] unless session_id
end
@@ -306,9 +311,9 @@ def commit_session(env, status, headers, body)
session.send(:load!) unless loaded_session?(session)
session_id ||= session.id || generate_sid
- session = session.to_hash
+ 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 e5b4d96

Please sign in to comment.