56ee9c67e25f5031bdd01092c4bbef93f7da4331
[feedcatcher.git] / vendor / rails / actionpack / lib / action_controller / flash.rb
1 module ActionController #:nodoc:
2 # The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed
3 # to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create
4 # action that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can
5 # then expose the flash to its template. Actually, that exposure is automatically done. Example:
6 #
7 # class PostsController < ActionController::Base
8 # def create
9 # # save post
10 # flash[:notice] = "Successfully created post"
11 # redirect_to posts_path(@post)
12 # end
13 #
14 # def show
15 # # doesn't need to assign the flash notice to the template, that's done automatically
16 # end
17 # end
18 #
19 # show.html.erb
20 # <% if flash[:notice] %>
21 # <div class="notice"><%= flash[:notice] %></div>
22 # <% end %>
23 #
24 # This example just places a string in the flash, but you can put any object in there. And of course, you can put as
25 # many as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.
26 #
27 # See docs on the FlashHash class for more details about the flash.
28 module Flash
29 def self.included(base)
30 base.class_eval do
31 include InstanceMethods
32 alias_method_chain :perform_action, :flash
33 alias_method_chain :reset_session, :flash
34 end
35 end
36
37 class FlashNow #:nodoc:
38 def initialize(flash)
39 @flash = flash
40 end
41
42 def []=(k, v)
43 @flash[k] = v
44 @flash.discard(k)
45 v
46 end
47
48 def [](k)
49 @flash[k]
50 end
51 end
52
53 class FlashHash < Hash
54 def initialize #:nodoc:
55 super
56 @used = {}
57 end
58
59 def []=(k, v) #:nodoc:
60 keep(k)
61 super
62 end
63
64 def update(h) #:nodoc:
65 h.keys.each { |k| keep(k) }
66 super
67 end
68
69 alias :merge! :update
70
71 def replace(h) #:nodoc:
72 @used = {}
73 super
74 end
75
76 # Sets a flash that will not be available to the next action, only to the current.
77 #
78 # flash.now[:message] = "Hello current action"
79 #
80 # This method enables you to use the flash as a central messaging system in your app.
81 # When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>).
82 # When you need to pass an object to the current action, you use <tt>now</tt>, and your object will
83 # vanish when the current action is done.
84 #
85 # Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.
86 def now
87 FlashNow.new(self)
88 end
89
90 # Keeps either the entire current flash or a specific flash entry available for the next action:
91 #
92 # flash.keep # keeps the entire flash
93 # flash.keep(:notice) # keeps only the "notice" entry, the rest of the flash is discarded
94 def keep(k = nil)
95 use(k, false)
96 end
97
98 # Marks the entire flash or a single flash entry to be discarded by the end of the current action:
99 #
100 # flash.discard # discard the entire flash at the end of the current action
101 # flash.discard(:warning) # discard only the "warning" entry at the end of the current action
102 def discard(k = nil)
103 use(k)
104 end
105
106 # Mark for removal entries that were kept, and delete unkept ones.
107 #
108 # This method is called automatically by filters, so you generally don't need to care about it.
109 def sweep #:nodoc:
110 keys.each do |k|
111 unless @used[k]
112 use(k)
113 else
114 delete(k)
115 @used.delete(k)
116 end
117 end
118
119 # clean up after keys that could have been left over by calling reject! or shift on the flash
120 (@used.keys - keys).each{ |k| @used.delete(k) }
121 end
122
123 private
124 # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
125 # use() # marks the entire flash as used
126 # use('msg') # marks the "msg" entry as used
127 # use(nil, false) # marks the entire flash as unused (keeps it around for one more action)
128 # use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action)
129 def use(k=nil, v=true)
130 unless k.nil?
131 @used[k] = v
132 else
133 keys.each{ |key| use(key, v) }
134 end
135 end
136 end
137
138 module InstanceMethods #:nodoc:
139 protected
140 def perform_action_with_flash
141 perform_action_without_flash
142 remove_instance_variable(:@_flash) if defined? @_flash
143 end
144
145 def reset_session_with_flash
146 reset_session_without_flash
147 remove_instance_variable(:@_flash) if defined? @_flash
148 end
149
150 # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
151 # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
152 # to put a new one.
153 def flash #:doc:
154 unless defined? @_flash
155 @_flash = session["flash"] ||= FlashHash.new
156 @_flash.sweep
157 end
158
159 @_flash
160 end
161 end
162 end
163 end