mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Added a much improved Flash module that allows for finer-grained control on expiration and allows you to flash the current action #839 [Caio Chassot]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@942 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
800b86e4c7
commit
a35cf348bf
5 changed files with 175 additions and 38 deletions
|
@ -1,5 +1,22 @@
|
|||
*SVN*
|
||||
|
||||
* Added a much improved Flash module that allows for finer-grained control on expiration and allows you to flash the current action #839 [Caio Chassot]. Example of flash.now:
|
||||
|
||||
class SomethingController < ApplicationController
|
||||
def save
|
||||
...
|
||||
if @something.save
|
||||
# will redirect, use flash
|
||||
flash['message'] = 'Save successful'
|
||||
redirect_to :action => 'list'
|
||||
else
|
||||
# no redirect, message is for current action, use flash.now
|
||||
flash.now['message'] = 'Save failed, review'
|
||||
render_action 'edit'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
* Added to_param call for parameters when composing an url using url_for from something else than strings #812 [Sam Stephenson]. Example:
|
||||
|
||||
class Page
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -179,7 +179,6 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
|||
# test the flash-based assertions with no flash at all
|
||||
def test_flash_assertions_negative
|
||||
process :nothing
|
||||
assert_flash_not_exists
|
||||
assert_flash_empty
|
||||
assert_flash_has_no 'hello'
|
||||
assert_flash_has_no 'qwerty'
|
||||
|
@ -230,7 +229,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
|||
# check the empty flashing
|
||||
def test_flash_me_naked
|
||||
process :flash_me_naked
|
||||
assert @response.has_flash?
|
||||
assert !@response.has_flash?
|
||||
assert !@response.has_flash_with_contents?
|
||||
end
|
||||
|
||||
|
|
|
@ -7,12 +7,26 @@ class FlashTest < Test::Unit::TestCase
|
|||
render_text "hello"
|
||||
end
|
||||
|
||||
def set_flash_now
|
||||
flash.now["that"] = "hello"
|
||||
@flash_copy = {}.update flash
|
||||
render_text "hello"
|
||||
end
|
||||
|
||||
def attempt_to_use_flash_now
|
||||
@flash_copy = {}.update flash
|
||||
@flashy = flash["that"]
|
||||
render_text "hello"
|
||||
end
|
||||
|
||||
def use_flash
|
||||
@flash_copy = {}.update flash
|
||||
@flashy = flash["that"]
|
||||
render_text "hello"
|
||||
end
|
||||
|
||||
def use_flash_and_keep_it
|
||||
@flash_copy = {}.update flash
|
||||
@flashy = flash["that"]
|
||||
keep_flash
|
||||
render_text "hello"
|
||||
|
@ -33,11 +47,11 @@ class FlashTest < Test::Unit::TestCase
|
|||
|
||||
@request.action = "use_flash"
|
||||
first_response = process_request
|
||||
assert_equal "hello", first_response.template.assigns["flash"]["that"]
|
||||
assert_equal "hello", first_response.template.assigns["flash_copy"]["that"]
|
||||
assert_equal "hello", first_response.template.assigns["flashy"]
|
||||
|
||||
second_response = process_request
|
||||
assert_nil second_response.template.assigns["flash"]["that"], "On second flash"
|
||||
assert_nil second_response.template.assigns["flash_copy"]["that"], "On second flash"
|
||||
end
|
||||
|
||||
def test_keep_flash
|
||||
|
@ -46,17 +60,28 @@ class FlashTest < Test::Unit::TestCase
|
|||
|
||||
@request.action = "use_flash_and_keep_it"
|
||||
first_response = process_request
|
||||
assert_equal "hello", first_response.template.assigns["flash"]["that"]
|
||||
assert_equal "hello", first_response.template.assigns["flash_copy"]["that"]
|
||||
assert_equal "hello", first_response.template.assigns["flashy"]
|
||||
|
||||
@request.action = "use_flash"
|
||||
second_response = process_request
|
||||
assert_equal "hello", second_response.template.assigns["flash"]["that"], "On second flash"
|
||||
assert_equal "hello", second_response.template.assigns["flash_copy"]["that"], "On second flash"
|
||||
|
||||
third_response = process_request
|
||||
assert_nil third_response.template.assigns["flash"]["that"], "On third flash"
|
||||
assert_nil third_response.template.assigns["flash_copy"]["that"], "On third flash"
|
||||
end
|
||||
|
||||
def test_flash_now
|
||||
@request.action = "set_flash_now"
|
||||
response = process_request
|
||||
assert_equal "hello", response.template.assigns["flash_copy"]["that"]
|
||||
|
||||
@request.action = "attempt_to_use_flash_now"
|
||||
first_response = process_request
|
||||
assert_nil first_response.template.assigns["flash_copy"]["that"]
|
||||
assert_nil first_response.template.assigns["flashy"]
|
||||
end
|
||||
|
||||
private
|
||||
def initialize_request_and_response
|
||||
@request = ActionController::TestRequest.new
|
||||
|
|
Loading…
Reference in a new issue