diff options
-rw-r--r-- | actionpack/CHANGELOG | 2 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/active_record_helper.rb | 22 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/form_helper.rb | 4 | ||||
-rw-r--r-- | actionpack/test/template/active_record_helper_test.rb | 23 | ||||
-rw-r--r-- | actionpack/test/template/form_helper_test.rb | 19 |
5 files changed, 64 insertions, 6 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 01e560f79d..f282f70dfc 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* error_messages_for and friends also work with local variables. #9699 [Frederick Cheung] + * Fix url_for, redirect_to, etc. with :controller => :symbol instead of 'string'. #8562, #9525 [Justin Lynn, Tarmo Tänav, shoe] * Use #require_library_or_gem to load the memcache library for the MemCache session and fragment cache stores. Closes #8662. [Rick] diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb index 08abdbd8a8..e2e35cb0bd 100644 --- a/actionpack/lib/action_view/helpers/active_record_helper.rb +++ b/actionpack/lib/action_view/helpers/active_record_helper.rb @@ -76,16 +76,21 @@ module ActionView # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. # This error message is wrapped in a <tt>DIV</tt> tag, which can be extended to include a +prepend_text+ and/or +append_text+ - # (to properly explain the error), and a +css_class+ to style it accordingly. As an example, let's say you have a model + # (to properly explain the error), and a +css_class+ to style it accordingly. +object+ should either be the name of an instance variable or + # the actual object. As an example, let's say you have a model # +post+ that has an error message on the +title+ attribute: # # <%= error_message_on "post", "title" %> => # <div class="formError">can't be empty</div> # + # <%= error_message_on @post, "title" %> => + # <div class="formError">can't be empty</div> + # # <%= error_message_on "post", "title", "Title simply ", " (or it won't work).", "inputError" %> => # <div class="inputError">Title simply can't be empty (or it won't work).</div> def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError") - if (obj = instance_variable_get("@#{object}")) && (errors = obj.errors.on(method)) + if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) && + (errors = obj.errors.on(method)) content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class) else '' @@ -101,6 +106,8 @@ module ActionView # * <tt>header_tag</tt> - Used for the header of the error div (default: h2) # * <tt>id</tt> - The id of the error div (default: errorExplanation) # * <tt>class</tt> - The class of the error div (default: errorExplanation) + # * <tt>object</tt> - The object (or array of objects) for which to display errors, + # if you need to escape the instance variable convention # * <tt>object_name</tt> - The object name to use in the header, or # any text that you prefer. If <tt>object_name</tt> is not set, the name of # the first object will be used. @@ -114,12 +121,21 @@ module ActionView # # error_messages_for 'user_common', 'user', :object_name => 'user' # + # If the objects cannot be located as instance variables, you can add an extra +object+ paremeter which gives the actual + # object (or array of objects to use) + # + # error_messages_for 'user', :object => @question.user + # # NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what # you need is significantly different from the default presentation, it makes plenty of sense to access the object.errors # instance yourself and set it up. View the source of this method to see how easy it is. def error_messages_for(*params) options = params.extract_options!.symbolize_keys - objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact + if object = options.delete(:object) + objects = [object].flatten + else + objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact + end count = objects.inject(0) {|sum, object| sum + object.errors.count } unless count.zero? html = {} diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 9bfc3041af..3b4e05bc1d 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -628,11 +628,11 @@ module ActionView end def error_message_on(method, prepend_text = "", append_text = "", css_class = "formError") - @template.error_message_on(@object_name, method, prepend_text, append_text, css_class) + @template.error_message_on(@object, method, prepend_text, append_text, css_class) end def error_messages(options = {}) - @template.error_messages_for(@object_name, options) + @template.error_messages_for(@object_name, options.merge(:object => @object)) end def submit(value = "Save changes", options = {}) diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb index 4a85ae1751..4630cbc1f3 100644 --- a/actionpack/test/template/active_record_helper_test.rb +++ b/actionpack/test/template/active_record_helper_test.rb @@ -181,6 +181,11 @@ class ActiveRecordHelperTest < Test::Unit::TestCase assert_dom_equal "<div class=\"formError\">can't be empty</div>", error_message_on(:post, :author_name) end + def test_error_message_on_no_instance_variable + other_post = @post + assert_dom_equal "<div class=\"formError\">can't be empty</div>", error_message_on(other_post, :author_name) + end + def test_error_message_on_should_use_options assert_dom_equal "<div class=\"differentError\">beforecan't be emptyafter</div>", error_message_on(:post, :author_name, "before", "after", "differentError") end @@ -203,7 +208,23 @@ class ActiveRecordHelperTest < Test::Unit::TestCase # should space object name assert_dom_equal %(<div class="errorExplanation" id="errorExplanation"><h2>2 errors prohibited this chunky bacon from being saved</h2><p>There were problems with the following fields:</p><ul><li>User email can't be empty</li><li>Author name can't be empty</li></ul></div>), error_messages_for(:user, :post, :object_name => "chunky_bacon") end - + + def test_error_messages_for_non_instance_variable + actual_user = @user + actual_post = @post + @user = nil + @post = nil + + #explicitly set object + assert_dom_equal %(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>), error_messages_for("post", :object => actual_post) + + #multiple objects + assert_dom_equal %(<div class="errorExplanation" id="errorExplanation"><h2>2 errors prohibited this user from being saved</h2><p>There were problems with the following fields:</p><ul><li>User email can't be empty</li><li>Author name can't be empty</li></ul></div>), error_messages_for("user", "post", :object => [actual_user, actual_post]) + + #nil object + assert_equal '', error_messages_for('user', :object => nil) + end + def test_form_with_string_multipart assert_dom_equal( %(<form action="create" enctype="multipart/form-data" method="post"><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>\n<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>), diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 1c842fc307..32529c66f7 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -527,6 +527,25 @@ class FormHelperTest < Test::Unit::TestCase assert_dom_equal expected, _erbout end + + def test_default_form_builder_no_instance_variable + post = @post + @post = nil + + _erbout = '' + form_for(:post, post) do |f| + _erbout.concat f.error_message_on('author_name') + _erbout.concat f.error_messages + end + + expected = %(<form action='http://www.example.com' method='post'>) + + %(<div class='formError'>can't be empty</div>) + + %(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>) + + %(</form>) + + assert_dom_equal expected, _erbout + + end # Perhaps this test should be moved to prototype helper tests. def test_remote_form_for_with_labelled_builder |