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*
|
*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:
|
* Added to_param call for parameters when composing an url using url_for from something else than strings #812 [Sam Stephenson]. Example:
|
||||||
|
|
||||||
class Page
|
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
|
# 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.
|
# 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
|
module Flash
|
||||||
|
|
||||||
def self.append_features(base) #:nodoc:
|
def self.append_features(base) #:nodoc:
|
||||||
super
|
super
|
||||||
base.before_filter(:fire_flash)
|
base.before_filter(:fire_flash)
|
||||||
base.after_filter(:clear_flash)
|
base.after_filter(:sweep_flash)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
class FlashNow #:nodoc:
|
||||||
# Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or
|
def initialize flash
|
||||||
# <tt>flash["notice"] = "hello"</tt> to put a new one.
|
@flash = flash
|
||||||
def flash #:doc:
|
end
|
||||||
if @session["flash"].nil?
|
|
||||||
@session["flash"] = {}
|
def []=(k, v)
|
||||||
@session["flashes"] ||= 0
|
@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
|
end
|
||||||
@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
|
end
|
||||||
|
|
||||||
# Can be called by any action that would like to keep the current content of the flash around for one more action.
|
private
|
||||||
def keep_flash #:doc:
|
|
||||||
@session["flashes"] = 0
|
# Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
|
||||||
end
|
# use() # marks the entire flash as used
|
||||||
|
# use('msg') # marks the "msg" entry as used
|
||||||
private
|
# use(nil, false) # marks the entire flash as unused (keeps it around for one more action)
|
||||||
# Records that the contents of @session["flash"] was flashed to the action
|
# use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action)
|
||||||
def fire_flash
|
def use(k=nil, v=true)
|
||||||
if @session["flash"]
|
unless k.nil?
|
||||||
@session["flashes"] += 1 unless @session["flash"].empty?
|
@used[k] = v
|
||||||
@assigns["flash"] = @session["flash"]
|
|
||||||
else
|
else
|
||||||
@assigns["flash"] = {}
|
keys.each{|key| use key, v }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear_flash
|
end
|
||||||
if @session["flash"] && (@session["flashes"].nil? || @session["flashes"] >= 1)
|
|
||||||
@session["flash"] = {}
|
|
||||||
@session["flashes"] = 0
|
protected
|
||||||
end
|
|
||||||
end
|
# 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
|
||||||
end
|
end
|
||||||
|
|
|
@ -168,7 +168,7 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
# do we have a flash?
|
# do we have a flash?
|
||||||
def has_flash?
|
def has_flash?
|
||||||
!session['flash'].nil?
|
!session['flash'].empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
# do we have a flash that has contents?
|
# do we have a flash that has contents?
|
||||||
|
@ -283,4 +283,4 @@ module Test
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -179,7 +179,6 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
||||||
# test the flash-based assertions with no flash at all
|
# test the flash-based assertions with no flash at all
|
||||||
def test_flash_assertions_negative
|
def test_flash_assertions_negative
|
||||||
process :nothing
|
process :nothing
|
||||||
assert_flash_not_exists
|
|
||||||
assert_flash_empty
|
assert_flash_empty
|
||||||
assert_flash_has_no 'hello'
|
assert_flash_has_no 'hello'
|
||||||
assert_flash_has_no 'qwerty'
|
assert_flash_has_no 'qwerty'
|
||||||
|
@ -230,7 +229,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
||||||
# check the empty flashing
|
# check the empty flashing
|
||||||
def test_flash_me_naked
|
def test_flash_me_naked
|
||||||
process :flash_me_naked
|
process :flash_me_naked
|
||||||
assert @response.has_flash?
|
assert !@response.has_flash?
|
||||||
assert !@response.has_flash_with_contents?
|
assert !@response.has_flash_with_contents?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,26 @@ class FlashTest < Test::Unit::TestCase
|
||||||
render_text "hello"
|
render_text "hello"
|
||||||
end
|
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
|
def use_flash
|
||||||
|
@flash_copy = {}.update flash
|
||||||
@flashy = flash["that"]
|
@flashy = flash["that"]
|
||||||
render_text "hello"
|
render_text "hello"
|
||||||
end
|
end
|
||||||
|
|
||||||
def use_flash_and_keep_it
|
def use_flash_and_keep_it
|
||||||
|
@flash_copy = {}.update flash
|
||||||
@flashy = flash["that"]
|
@flashy = flash["that"]
|
||||||
keep_flash
|
keep_flash
|
||||||
render_text "hello"
|
render_text "hello"
|
||||||
|
@ -33,11 +47,11 @@ class FlashTest < Test::Unit::TestCase
|
||||||
|
|
||||||
@request.action = "use_flash"
|
@request.action = "use_flash"
|
||||||
first_response = process_request
|
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"]
|
assert_equal "hello", first_response.template.assigns["flashy"]
|
||||||
|
|
||||||
second_response = process_request
|
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
|
end
|
||||||
|
|
||||||
def test_keep_flash
|
def test_keep_flash
|
||||||
|
@ -46,17 +60,28 @@ class FlashTest < Test::Unit::TestCase
|
||||||
|
|
||||||
@request.action = "use_flash_and_keep_it"
|
@request.action = "use_flash_and_keep_it"
|
||||||
first_response = process_request
|
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"]
|
assert_equal "hello", first_response.template.assigns["flashy"]
|
||||||
|
|
||||||
@request.action = "use_flash"
|
@request.action = "use_flash"
|
||||||
second_response = process_request
|
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
|
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
|
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
|
private
|
||||||
def initialize_request_and_response
|
def initialize_request_and_response
|
||||||
@request = ActionController::TestRequest.new
|
@request = ActionController::TestRequest.new
|
||||||
|
|
Loading…
Reference in a new issue