From 2456eb89353c744ca0f003939c97a50c3bcecb23 Mon Sep 17 00:00:00 2001 From: Yaroslav Markin Date: Wed, 26 Nov 2008 22:08:42 +0300 Subject: [PATCH] Introduce error_messages_on() helper. Unlike error_message_on(), helper joins *all* error messages attached to object's method (using Array#to_sentence). --- .../action_view/helpers/active_record_helper.rb | 35 +++++++++++- actionpack/lib/action_view/helpers/form_helper.rb | 4 + .../test/template/active_record_helper_test.rb | 61 +++++++++++++------- actionpack/test/template/form_helper_test.rb | 26 ++++++--- 4 files changed, 94 insertions(+), 32 deletions(-) diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb index 8b56d24..82bc741 100644 --- a/actionpack/lib/action_view/helpers/active_record_helper.rb +++ b/actionpack/lib/action_view/helpers/active_record_helper.rb @@ -129,6 +129,39 @@ module ActionView end end + # Returns a string containing all error messages attached to the +method+ on the +object+ if one exists. + # Note that error messages are joined using Array#to_sentence. + # This error message is wrapped in a DIV 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. +object+ should either be the name of an instance variable or the actual object. The method can be + # passed in either as a string or a symbol. + # As an example, let's say you have a model @post that has two error messages on the +title+ attribute: + # + # <%= error_messages_on "post", "title" %> + # # =>
can't be empty and is too short (minimum is 3 characters)
+ # + # <%= error_messages_on @post, :title %> + # # =>
can't be empty and is too short (minimum is 3 characters)
+ # + # <%= error_messages_on "post", "title", + # :prepend_text => "Title simply ", + # :append_text => " (or it won't work).", + # :css_class => "inputError" %> + def error_messages_on(object, method, *args) + options = args.extract_options! + options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError') + + if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) && + (errors = obj.errors.on(method)) + content_tag("div", + "#{options[:prepend_text]}#{errors.is_a?(Array) ? errors.to_sentence : errors}#{options[:append_text]}", + :class => options[:css_class] + ) + else + '' + end + end + # Returns a string with a DIV containing all of the error messages for the objects located as instance variables by the names # given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are # provided. @@ -211,7 +244,7 @@ module ActionView '' end end - + private def all_input_tags(record, record_name, options) input_block = options[:input_block] || default_input_block diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 621e294..1be8eee 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -786,6 +786,10 @@ module ActionView @template.error_message_on(@object, method, *args) end + def error_messages_on(method, *args) + @template.error_messages_on(@object, method, *args) + end + def error_messages(options = {}) @template.error_messages_for(@object_name, objectify_options(options)) end diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb index e46f95d..5031200 100644 --- a/actionpack/test/template/active_record_helper_test.rb +++ b/actionpack/test/template/active_record_helper_test.rb @@ -26,7 +26,7 @@ class ActiveRecordHelperTest < ActionView::TestCase def on(field) case field.to_s when "author_name" - "can't be empty" + [ "can't be empty", "is too short (minimum is 3 characters)" ] when "body" true else @@ -34,8 +34,8 @@ class ActiveRecordHelperTest < ActionView::TestCase end end def empty?() false end - def count() 1 end - def full_messages() [ "Author name can't be empty" ] end + def count() 2 end + def full_messages() [ "Author name can't be empty", "Author name is too short (minimum is 3 characters)" ] end }.new end @@ -189,10 +189,10 @@ class ActiveRecordHelperTest < ActionView::TestCase end def test_error_for_block - assert_dom_equal %(

1 error prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post") - assert_equal %(

1 error prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :class => "errorDeathByClass", :id => "errorDeathById", :header_tag => "h1") - assert_equal %(

1 error prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :class => nil, :id => "errorDeathById", :header_tag => "h1") - assert_equal %(

1 error prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :class => "errorDeathByClass", :id => nil, :header_tag => "h1") + assert_dom_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post") + assert_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :class => "errorDeathByClass", :id => "errorDeathById", :header_tag => "h1") + assert_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :class => nil, :id => "errorDeathById", :header_tag => "h1") + assert_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :class => "errorDeathByClass", :id => nil, :header_tag => "h1") end def test_error_messages_for_handles_nil @@ -212,35 +212,52 @@ class ActiveRecordHelperTest < ActionView::TestCase assert_dom_equal "
can't be empty
", error_message_on(other_post, :author_name) end - def test_error_message_on_with_options_hash - assert_dom_equal "
beforecan't be emptyafter
", error_message_on(:post, :author_name, :css_class => 'differentError', :prepend_text => 'before', :append_text => 'after') + def test_error_messages_on_with_options_hash + assert_dom_equal "
beforecan't be empty and is too short (minimum is 3 characters)after
", error_messages_on(:post, :author_name, :css_class => 'differentError', :prepend_text => 'before', :append_text => 'after') + end + + def test_error_messages_on_handles_nil + assert_equal "", error_messages_on("notthere", "notthere") + end + + def test_error_messages_on + assert_dom_equal "
can't be empty and is too short (minimum is 3 characters)
", error_messages_on(:post, :author_name) + end + + def test_error_messages_on_no_instance_variable + other_post = @post + assert_dom_equal "
can't be empty and is too short (minimum is 3 characters)
", error_messages_on(other_post, :author_name) + end + + def test_error_messages_on_with_options_hash + assert_dom_equal "
beforecan't be empty and is too short (minimum is 3 characters)after
", error_messages_on(:post, :author_name, :css_class => 'differentError', :prepend_text => 'before', :append_text => 'after') end def test_error_messages_for_many_objects - assert_dom_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", "user") + assert_dom_equal %(

3 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", "user") # reverse the order, error order changes and so does the title - assert_dom_equal %(

2 errors prohibited this user from being saved

There were problems with the following fields:

), error_messages_for("user", "post") + assert_dom_equal %(

3 errors prohibited this user from being saved

There were problems with the following fields:

), error_messages_for("user", "post") # add the default to put post back in the title - assert_dom_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("user", "post", :object_name => "post") + assert_dom_equal %(

3 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("user", "post", :object_name => "post") # symbols work as well - assert_dom_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for(:user, :post, :object_name => :post) + assert_dom_equal %(

3 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for(:user, :post, :object_name => :post) # any default works too - assert_dom_equal %(

2 errors prohibited this monkey from being saved

There were problems with the following fields:

), error_messages_for(:user, :post, :object_name => "monkey") + assert_dom_equal %(

3 errors prohibited this monkey from being saved

There were problems with the following fields:

), error_messages_for(:user, :post, :object_name => "monkey") # should space object name - assert_dom_equal %(

2 errors prohibited this chunky bacon from being saved

There were problems with the following fields:

), error_messages_for(:user, :post, :object_name => "chunky_bacon") + assert_dom_equal %(

3 errors prohibited this chunky bacon from being saved

There were problems with the following fields:

), error_messages_for(:user, :post, :object_name => "chunky_bacon") # hide header and explanation messages with nil or empty string - assert_dom_equal %(
), error_messages_for(:user, :post, :header_message => nil, :message => "") + assert_dom_equal %(
), error_messages_for(:user, :post, :header_message => nil, :message => "") # override header and explanation messages header_message = "Yikes! Some errors" message = "Please fix the following fields and resubmit:" - assert_dom_equal %(

#{header_message}

#{message}

), error_messages_for(:user, :post, :header_message => header_message, :message => message) + assert_dom_equal %(

#{header_message}

#{message}

), error_messages_for(:user, :post, :header_message => header_message, :message => message) end def test_error_messages_for_non_instance_variable @@ -249,13 +266,13 @@ class ActiveRecordHelperTest < ActionView::TestCase @user = nil @post = nil - #explicitly set object - assert_dom_equal %(

1 error prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :object => actual_post) + # explicitly set object + assert_dom_equal %(

2 errors prohibited this post from being saved

There were problems with the following fields:

), error_messages_for("post", :object => actual_post) - #multiple objects - assert_dom_equal %(

2 errors prohibited this user from being saved

There were problems with the following fields:

), error_messages_for("user", "post", :object => [actual_user, actual_post]) + # multiple objects + assert_dom_equal %(

3 errors prohibited this user from being saved

There were problems with the following fields:

), error_messages_for("user", "post", :object => [actual_user, actual_post]) - #nil object + # nil object assert_equal '', error_messages_for('user', :object => nil) end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 52e8bf3..ccaa2e9 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -39,10 +39,14 @@ class FormHelperTest < ActionView::TestCase @comment = Comment.new def @post.errors() Class.new{ - def on(field); "can't be empty" if field == "author_name"; end + def on(field) + ["can't be empty", "is too short (minimum is 3 characters)"] if field == "author_name" + end def empty?() false end - def count() 1 end - def full_messages() [ "Author name can't be empty" ] end + def count() 2 end + def full_messages() + [ "Author name can't be empty", "Author name is too short (minimum is 3 characters)" ] + end }.new end def @post.id; 123; end @@ -775,13 +779,15 @@ class FormHelperTest < ActionView::TestCase def test_default_form_builder_with_active_record_helpers form_for(:post, @post) do |f| - concat f.error_message_on('author_name') - concat f.error_messages + concat f.error_message_on('author_name') + concat f.error_messages_on('author_name') + concat f.error_messages end expected = %(
) + %(
can't be empty
) + - %(

1 error prohibited this post from being saved

There were problems with the following fields:

  • Author name can't be empty
) + + %(
can't be empty and is too short (minimum is 3 characters)
) + + %(

2 errors prohibited this post from being saved

There were problems with the following fields:

  • Author name can't be empty
  • Author name is too short (minimum is 3 characters)
) + %(
) assert_dom_equal expected, output_buffer @@ -793,13 +799,15 @@ class FormHelperTest < ActionView::TestCase @post = nil form_for(:post, post) do |f| - concat f.error_message_on('author_name') - concat f.error_messages + concat f.error_message_on('author_name') + concat f.error_messages_on('author_name') + concat f.error_messages end expected = %(
) + %(
can't be empty
) + - %(

1 error prohibited this post from being saved

There were problems with the following fields:

  • Author name can't be empty
) + + %(
can't be empty and is too short (minimum is 3 characters)
) + + %(

2 errors prohibited this post from being saved

There were problems with the following fields:

  • Author name can't be empty
  • Author name is too short (minimum is 3 characters)
) + %(
) assert_dom_equal expected, output_buffer -- 1.6.0.4