diff options
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r-- | actionpack/lib/action_controller/flash.rb | 154 | ||||
-rw-r--r-- | actionpack/lib/action_controller/test_process.rb | 4 |
2 files changed, 127 insertions, 31 deletions
diff --git a/actionpack/lib/action_controller/flash.rb b/actionpack/lib/action_controller/flash.rb index b4e8d75bf6..e3a8a8c8c4 100644 --- a/actionpack/lib/action_controller/flash.rb +++ b/actionpack/lib/action_controller/flash.rb @@ -21,45 +21,141 @@ module ActionController #:nodoc: # # This example just places a string in the flash, but you can put any object in there. And of course, you can put as many # as you like at a time too. Just remember: They'll be gone by the time the next action has been performed. + # + # See docs on the FlashHash class for more details about the flash. module Flash + def self.append_features(base) #:nodoc: super base.before_filter(:fire_flash) - base.after_filter(:clear_flash) + base.after_filter(:sweep_flash) end - protected - # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or - # <tt>flash["notice"] = "hello"</tt> to put a new one. - def flash #:doc: - if @session["flash"].nil? - @session["flash"] = {} - @session["flashes"] ||= 0 + class FlashNow #:nodoc: + def initialize flash + @flash = flash + end + + def []=(k, v) + @flash[k] = v + @flash.discard(k) + v + end + end + + class FlashHash < Hash + + def initialize #:nodoc: + super + @used = {} + end + + def []=(k, v) #:nodoc: + keep(k) + super + end + + def update h #:nodoc: + h.keys.each{|k| discard k } + super + end + + alias merge! update + + def replace h #:nodoc: + @used = {} + super + end + + # Sets a flash that will not be available to the next action, only to the current. + # + # flash.now["message"] = "Hello current action" + # + # This method enables you to use the flash as a central messaging system in your app. + # When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>). + # When you need to pass an object to the current action, you use <tt>now</tt>, and your object will + # vanish when the current action is done. + # + # Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>. + def now + FlashNow.new self + end + + # Keeps either the entire current flash or a specific flash entry available for the next action: + # + # flash.keep # keeps the entire flash + # flash.keep("notice") # keeps only the "notice" entry, the rest of the flash is discarded + def keep(k=nil) + use(k, false) + end + + # Marks the entire flash or a single flash entry to be discarded by the end of the current action + # + # flash.keep # keep entire flash available for the next action + # flash.discard('warning') # discard the "warning" entry (it'll still be available for the current action) + def discard(k=nil) + use(k) + end + + # Mark for removal entries that were kept, and delete unkept ones. + # + # This method is called automatically by filters, so you generally don't need to care about it. + def sweep #:nodoc: + keys.each do |k| + unless @used[k] + use(k) + else + delete(k) + @used.delete(k) + end end - @session["flash"] - end - - # Can be called by any action that would like to keep the current content of the flash around for one more action. - def keep_flash #:doc: - @session["flashes"] = 0 - end - - private - # Records that the contents of @session["flash"] was flashed to the action - def fire_flash - if @session["flash"] - @session["flashes"] += 1 unless @session["flash"].empty? - @assigns["flash"] = @session["flash"] + (@used.keys - keys).each{|k| @used.delete k } # clean up after keys that could have been left over by calling reject! or shift on the flash + end + + private + + # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods + # use() # marks the entire flash as used + # use('msg') # marks the "msg" entry as used + # use(nil, false) # marks the entire flash as unused (keeps it around for one more action) + # use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action) + def use(k=nil, v=true) + unless k.nil? + @used[k] = v else - @assigns["flash"] = {} + keys.each{|key| use key, v } end end - def clear_flash - if @session["flash"] && (@session["flashes"].nil? || @session["flashes"] >= 1) - @session["flash"] = {} - @session["flashes"] = 0 - end - end + end + + + protected + + # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or + # <tt>flash["notice"] = "hello"</tt> to put a new one. + def flash #:doc: + @session['flash'] ||= FlashHash.new + end + + # deprecated. use <tt>flash.keep</tt> instead + def keep_flash #:doc: + flash.keep + end + + + private + + # marks flash entries as used and expose the flash to the view + def fire_flash + flash.discard + @assigns["flash"] = flash + end + + # deletes the flash entries that were not marked for keeping + def sweep_flash + flash.sweep + end + end end diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb index e3ab045a12..3d9a335eff 100644 --- a/actionpack/lib/action_controller/test_process.rb +++ b/actionpack/lib/action_controller/test_process.rb @@ -168,7 +168,7 @@ module ActionController #:nodoc: # do we have a flash? def has_flash? - !session['flash'].nil? + !session['flash'].empty? end # do we have a flash that has contents? @@ -283,4 +283,4 @@ module Test end end end -end
\ No newline at end of file +end |