~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/actionpack/lib/action_controller/flash.rb

  • Committer: Michael Forrest
  • Date: 2010-10-15 16:28:50 UTC
  • Revision ID: michael.forrest@canonical.com-20101015162850-tj2vchanv0kr0dun
refrozeĀ gems

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
      def store(session, key = "flash")
 
124
        return if self.empty?
 
125
        session[key] = self
 
126
      end
 
127
 
 
128
      private
 
129
        # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
 
130
        #     use()               # marks the entire flash as used
 
131
        #     use('msg')          # marks the "msg" entry as used
 
132
        #     use(nil, false)     # marks the entire flash as unused (keeps it around for one more action)
 
133
        #     use('msg', false)   # marks the "msg" entry as unused (keeps it around for one more action)
 
134
        def use(k=nil, v=true)
 
135
          unless k.nil?
 
136
            @used[k] = v
 
137
          else
 
138
            keys.each{ |key| use(key, v) }
 
139
          end
 
140
        end
 
141
    end
 
142
 
 
143
    module InstanceMethods #:nodoc:
 
144
      protected
 
145
        def perform_action_with_flash
 
146
          perform_action_without_flash
 
147
          if defined? @_flash
 
148
            @_flash.store(session)
 
149
            remove_instance_variable(:@_flash)
 
150
          end
 
151
        end
 
152
 
 
153
        def reset_session_with_flash
 
154
          reset_session_without_flash
 
155
          remove_instance_variable(:@_flash) if defined? @_flash
 
156
        end
 
157
 
 
158
        # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
 
159
        # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
 
160
        # to put a new one.
 
161
        def flash #:doc:
 
162
          if !defined?(@_flash)
 
163
            @_flash = session["flash"] || FlashHash.new
 
164
            @_flash.sweep
 
165
          end
 
166
 
 
167
          @_flash
 
168
        end
 
169
    end
 
170
  end
 
171
end