Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/branches/1-2-stable/actionpack/lib/action_controller/flash.rb

Revision 5021, 6.1 kB (checked in by david, 2 years ago)

caller is necessary for proper trace in deprecation

Line 
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 action
4   # that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can then expose
5   # the flash to its template. Actually, that exposure is automatically done. Example:
6   #
7   #   class WeblogController < ActionController::Base
8   #     def create
9   #       # save post
10   #       flash[:notice] = "Successfully created post"
11   #       redirect_to :action => "display", :params => { :id => post.id }
12   #     end
13   #
14   #     def display
15   #       # doesn't need to assign the flash notice to the template, that's done automatically
16   #     end
17   #   end
18   #
19   #   display.rhtml
20   #     <% if flash[:notice] %><div class="notice"><%= flash[:notice] %></div><% end %>
21   #
22   # 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
23   # as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.
24   #
25   # See docs on the FlashHash class for more details about the flash.
26   module Flash
27     def self.included(base)
28       base.send :include, InstanceMethods
29
30       base.class_eval do
31         alias_method_chain :assign_shortcuts, :flash
32         alias_method_chain :process_cleanup,  :flash
33         alias_method_chain :reset_session,    :flash
34       end
35     end
36    
37    
38     class FlashNow #:nodoc:
39       def initialize(flash)
40         @flash = flash
41       end
42      
43       def []=(k, v)
44         @flash[k] = v
45         @flash.discard(k)
46         v
47       end
48      
49       def [](k)
50         @flash[k]
51       end
52     end
53    
54     class FlashHash < Hash
55       def initialize #:nodoc:
56         super
57         @used = {}
58       end
59      
60       def []=(k, v) #:nodoc:
61         keep(k)
62         super
63       end
64      
65       def update(h) #:nodoc:
66         h.keys.each{ |k| discard(k) }
67         super
68       end
69      
70       alias :merge! :update
71      
72       def replace(h) #:nodoc:
73         @used = {}
74         super
75       end
76    
77       # Sets a flash that will not be available to the next action, only to the current.
78       #
79       #     flash.now[:message] = "Hello current action"
80       #
81       # This method enables you to use the flash as a central messaging system in your app.
82       # When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>).
83       # When you need to pass an object to the current action, you use <tt>now</tt>, and your object will
84       # vanish when the current action is done.
85       #
86       # Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.
87       def now
88         FlashNow.new self
89       end
90    
91       # Keeps either the entire current flash or a specific flash entry available for the next action:
92       #
93       #    flash.keep            # keeps the entire flash
94       #    flash.keep(:notice)   # keeps only the "notice" entry, the rest of the flash is discarded
95       def keep(k = nil)
96         use(k, false)
97       end
98    
99       # Marks the entire flash or a single flash entry to be discarded by the end of the current action
100       #
101       #     flash.keep                 # keep entire flash available for the next action
102       #     flash.discard(:warning)    # discard the "warning" entry (it'll still be available for the current action)
103       def discard(k = nil)
104         use(k)
105       end
106    
107       # Mark for removal entries that were kept, and delete unkept ones.
108       #
109       # This method is called automatically by filters, so you generally don't need to care about it.
110       def sweep #:nodoc:
111         keys.each do |k|
112           unless @used[k]
113             use(k)
114           else
115             delete(k)
116             @used.delete(k)
117           end
118         end
119
120         (@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
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       def assign_shortcuts_with_flash(request, response) #:nodoc:
140         assign_shortcuts_without_flash(request, response)
141         flash(:refresh)
142       end
143      
144       def process_cleanup_with_flash
145         flash.sweep if @_session
146         process_cleanup_without_flash
147       end
148
149       def reset_session_with_flash
150         reset_session_without_flash
151         remove_instance_variable(:@_flash)
152         flash(:refresh)
153       end
154      
155       protected
156         # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or
157         # <tt>flash["notice"] = "hello"</tt> to put a new one.
158         # Note that if sessions are disabled only flash.now will work.
159         def flash(refresh = false) #:doc:
160           if !defined?(@_flash) || refresh
161             @_flash =
162               if session.is_a?(Hash)
163                 # don't put flash in session if disabled
164                 FlashHash.new
165               else
166                 # otherwise, session is a CGI::Session or a TestSession
167                 # so make sure it gets retrieved from/saved to session storage after request processing
168                 session["flash"] ||= FlashHash.new
169               end
170           end
171
172           @_flash
173         end
174
175         # deprecated. use <tt>flash.keep</tt> instead
176         def keep_flash #:doc:
177           ActiveSupport::Deprecation.warn 'keep_flash is deprecated; use flash.keep instead.', caller
178           flash.keep
179         end
180     end
181   end
182 end
Note: See TracBrowser for help on using the browser.