Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Browse files

Added :alert, :notice, and :flash as options to ActionController::Bas…

…e#redirect_to that'll automatically set the proper flash before the redirection [DHH] Added ActionController::Base#notice/= and ActionController::Base#alert/= as a convenience accessors in both the controller and the view for flash[:notice]/= and flash[:alert]/= [DHH]
  • Loading branch information...
1 parent 48cd7df commit e6cadd422b72ba9818cc2f3b22243a6aa754c9f8 @dhh dhh committed
11 actionpack/CHANGELOG
@@ -1,5 +1,16 @@
+* Added :alert, :notice, and :flash as options to ActionController::Base#redirect_to that'll automatically set the proper flash before the redirection [DHH]. Examples:
+ flash[:notice] = 'Post was created'
+ redirect_to(@post)
+ ...becomes:
+ redirect_to(@post, :notice => 'Post was created')
+* Added ActionController::Base#notice/= and ActionController::Base#alert/= as a convenience accessors in both the controller and the view for flash[:notice]/= and flash[:alert]/= [DHH]
* Added cookies.permanent, cookies.signed, and cookies.permanent.signed accessor for common cookie actions [DHH]. Examples:
cookies.permanent[:prefers_open_id] = true
19 actionpack/lib/action_controller/base.rb
@@ -1092,10 +1092,19 @@ def default_url_options(options = nil)
# The redirection happens as a "302 Moved" header unless otherwise specified.
# Examples:
- # redirect_to post_url(@post), :status=>:found
- # redirect_to :action=>'atom', :status=>:moved_permanently
- # redirect_to post_url(@post), :status=>301
- # redirect_to :action=>'atom', :status=>302
+ # redirect_to post_url(@post), :status => :found
+ # redirect_to :action=>'atom', :status => :moved_permanently
+ # redirect_to post_url(@post), :status => 301
+ # redirect_to :action=>'atom', :status => 302
+ #
+ # It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names
+ # +alert+ and +notice+ as well as a general purpose +flash+ bucket.
+ #
+ # Examples:
+ # redirect_to post_url(@post), :alert => "Watch it, mister!"
+ # redirect_to post_url(@post), :status=> :found, :notice => "Pay attention to the road"
+ # redirect_to post_url(@post), :status => 301, :flash => { :updated_post_id => }
+ # redirect_to { :action=>'atom' }, :alert => "Something serious happened"
# When using <tt>redirect_to :back</tt>, if there is no referrer,
# RedirectBackError will be raised. You may specify some fallback
@@ -1412,7 +1421,7 @@ def process_cleanup
Base.class_eval do
- [ Filters, Layout, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
+ [ Filters, Layout, Benchmarking, Rescue, MimeResponds, Helpers, Flash,
Cookies, Caching, Verification, Streaming, SessionManagement,
HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods,
RecordIdentifier, RequestForgeryProtection, Translation
42 actionpack/lib/action_controller/flash.rb
@@ -29,8 +29,13 @@ module Flash
def self.included(base)
base.class_eval do
include InstanceMethods
alias_method_chain :perform_action, :flash
alias_method_chain :reset_session, :flash
+ alias_method_chain :redirect_to, :flash
+ helper_method :alert
+ helper_method :notice
@@ -155,6 +160,22 @@ def reset_session_with_flash
remove_instance_variable(:@_flash) if defined? @_flash
+ def redirect_to_with_flash(options = {}, response_status_and_flash = {}) #:doc:
+ if alert = response_status_and_flash.delete(:alert)
+ flash[:alert] = alert
+ end
+ if notice = response_status_and_flash.delete(:notice)
+ flash[:notice] = notice
+ end
+ if other_flashes = response_status_and_flash.delete(:flash)
+ flash.update(other_flashes)
+ end
+ redirect_to_without_flash(options, response_status_and_flash)
+ 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.
@@ -166,6 +187,27 @@ def flash #:doc:
+ # Convenience accessor for flash[:alert]
+ def alert
+ flash[:alert]
+ end
+ # Convenience accessor for flash[:alert]=
+ def alert=(message)
+ flash[:alert] = message
+ end
+ # Convenience accessor for flash[:notice]
+ def notice
+ flash[:notice]
+ end
+ # Convenience accessor for flash[:notice]=
+ def notice=(message)
+ flash[:notice] = message
+ end
29 actionpack/test/controller/flash_test.rb
@@ -71,6 +71,18 @@ def halt_and_redir
redirect_to :action => "std_action"
@flash_copy = {}.update(flash)
+ def redirect_with_alert
+ redirect_to '/nowhere', :alert => "Beware the nowheres!"
+ end
+ def redirect_with_notice
+ redirect_to '/somewhere', :notice => "Good luck in the somewheres!"
+ end
+ def redirect_with_other_flashes
+ redirect_to '/wonderland', :flash => { :joyride => "Horses!" }
+ end
tests TestController
@@ -144,4 +156,19 @@ def test_does_not_set_the_session_if_the_flash_is_empty
get :std_action
assert_nil session["flash"]
+ def test_redirect_to_with_alert
+ get :redirect_with_alert
+ assert_equal "Beware the nowheres!", @controller.send(:flash)[:alert]
+ end
+ def test_redirect_to_with_notice
+ get :redirect_with_notice
+ assert_equal "Good luck in the somewheres!", @controller.send(:flash)[:notice]
+ end
+ def test_redirect_to_with_other_flashes
+ get :redirect_with_other_flashes
+ assert_equal "Horses!", @controller.send(:flash)[:joyride]
+ end
6 railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb
@@ -44,8 +44,7 @@ def create
respond_to do |format|
if @<%= file_name %>.save
- flash[:notice] = '<%= class_name %> was successfully created.'
- format.html { redirect_to(@<%= file_name %>) }
+ format.html { redirect_to(@<%= file_name %>, :notice => '<%= class_name %> was successfully created.') }
format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> }
format.html { render :action => "new" }
@@ -61,8 +60,7 @@ def update
respond_to do |format|
if @<%= file_name %>.update_attributes(params[:<%= file_name %>])
- flash[:notice] = '<%= class_name %> was successfully updated.'
- format.html { redirect_to(@<%= file_name %>) }
+ format.html { redirect_to(@<%= file_name %>, :notice => '<%= class_name %> was successfully updated.') }
format.xml { head :ok }
format.html { render :action => "edit" }
2  railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb
@@ -9,7 +9,7 @@
-<p style="color: green"><%%= flash[:notice] %></p>
+<p style="color: green"><%%= notice %></p>
<%%= yield %>

27 comments on commit e6cadd4


While I like the helper methods for notice/alert, I'm not sure that I'd end up using that. Most of the time that we are display flash messages, we want to make sure there are any flashes set before we attempt to render the notice/alert out.

We follow this pattern so that the HTML markup is consistent across our projects:

I assume that we can still check on whether flash has anything in it?


What about flash arrays? e.g. when you have several messages that belong into the same flash key.


Well I use flash[:error] not flash[:alert] - naughty me.


Why not use @response.flash[:notice] instead of @controller.send(:flash)[:notice] ?


robby, you can keep using whatever you're doing now just fine. This pattern will allow me to extract tons of code from all my apps though.
ss, because it's a protected method.


Nice, but I wonder if the :flash => {} option isn't a bit over the top. It doesn't really save much code or make things more readable.


Great addition. Not only is it more succinct, I think it actually does a better job than the usual method of expressing how the flash behaves -- it's usually a bit confusing to beginners that the flash applies to the next request, and not the current request (almost no other setting in rails behaves that way). People usually seem to be surprised that working in the current request is the special case (

Tying it in to the redirect makes the actual behavior a natural assumption.


Can any light be shed on the naming of :alert versus :error ?
For some reason I've only ever seen :error (I've not seen the use of :alert until now).


dhh, thanks :)


This is a great change! I always hated that it took two lines to accomplish such a simple thing.


dallas, we've been using alert for everything at 37signals. It doesn't really matter. Just that there is one accessor for go and one for stop.



Your AWDROR ("21.3 Flash—Communicating between Actions") uses flash[:notice], flash[:error] and flash[:warning]


rmoriz, I'll make sure to get that updated for the next version of the book.



Thanks for your answer on that. I've basically learned the majority of what I know of Rails from dev teams I've been a part of and from the Agile Web Development with Rails book. :error, :alert; tom·ay·to, tom·ah·to


And why can't error and success be added?

Array has first, second, third, etc.

Go (green), Stop (red)....... how about Notice (yellow) ?


jko, there's not enough difference to justify the extensions. If you're using :success now and want to use the built-in helpers, just switch to :notice. Or if you're married to :success, just overwrite redirect_to in your application.rb to pickup :success as well.


These two don't belong in the same function, it's just more bloat. For those of you crying about having to have an "extra" line of code, are you serious? If it's that big of a deal, write a helper that will deal with your flash then redirect.


It’s would be nice if

class UsersController < ApplicationController
  def create
     @user = User.create(params[:user])
     redirect_to user_path(@user), :notice => true

automatically look at ‘users.notice.flash’ in I18n locales.


#tenth ?


Great idea guillaumegentil !


@guillaumegentil really good idea,
Most of my flashes are wrapped with t() and such, behavior will really help to clean up the controllers code more


While I don't really care about the specific syntax/lexicon in this particular case, if there is going to be an established convention for something like this, it does seem like alert/notice are really very ambiguous. In fact, to me they almost seem synonymous (which isn't just not very ruby, it's not very smart). I'm sure they work fine at 37S, and they don't even seem to be causing any confusion here (we all know alert is a stop, so it's not an argument of 'which one means what?!'), but that doesn't mean they're the best option to use as the convention. Even if this is the only place these terms are hardcoded in, that's enough impetus to sway probably 90% of new projects to name their flashes this way.

I would think ten minutes of looking through a thesaurus could yield a couple words that clearly mean what they represent, which would result in most new Rails projects having meaningfully named flashes, rather than having flashes that everyone-knows-what-they-mean-even-though-it's-not-really-that-obvious. This seems like it's a no brainer; why go with option 1, which is fine but not great, when option 2 is just as easy to implement and better? If 37S is married to the crappy option, 'just overwrite redirect_to in your application.rb', no?


I personally really like the convention José using in InheritedResources: :success and :failure

I use that one in all my projects, so I'm not that effected but this change to the Rails core - but I do agree with @farski that these flashes are a bit of "confusing naming convention". That's my 2 cents. =)


The important thing about this commit is the combination of redirect with flash. The notice and alert helpers are mostly sugar (and they're not really synonymous with #tenth -- flash[:notice] and flash[:alert] are pretty idiomatic in the apps I've ever done).


Would be nice if you could also do this:

render :notice => 'foo'

which would set[:notice] before rendering the template.


We'll I upgraded from 2.3.6 to 2.3.10 and I'm nolonger able to access the notice like this ( flash[:notice] )

Now I can only access it via the controller like this ( controller.session[:flash][:notice] )

And notice does not work.


It's very annoying that something as basic as flash is such a headache.

This is now the only way to access your flash notice? flash[:notice] and notice do not work.

<%= controller.session[:flash][:notice] %>
Please sign in to comment.
Something went wrong with that request. Please try again.