From 459cc1ecb84aea273ecf8183fb791f61e26c19b0 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Sun, 7 Oct 2007 19:50:30 +0000
Subject: [PATCH] error_messages_for and friends also work with local
variables. Closes #9699.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7779 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
---
actionpack/CHANGELOG | 2 ++
.../helpers/active_record_helper.rb | 22 ++++++++++++++++---
.../lib/action_view/helpers/form_helper.rb | 4 ++--
.../template/active_record_helper_test.rb | 21 ++++++++++++++++++
actionpack/test/template/form_helper_test.rb | 19 ++++++++++++++++
5 files changed, 63 insertions(+), 5 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 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. 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" %> =>
#
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
# * header_tag - Used for the header of the error div (default: h2)
# * id - The id of the error div (default: errorExplanation)
# * class - The class of the error div (default: errorExplanation)
+ # * object - The object (or array of objects) for which to display errors,
+ # if you need to escape the instance variable convention
# * object_name - The object name to use in the header, or
# any text that you prefer. If object_name 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 "
", error_message_on(other_post, :author_name)
+ end
+
def test_error_message_on_should_use_options
assert_dom_equal "
beforecan't be emptyafter
", 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 %(
2 errors prohibited this chunky bacon from being saved