From c49a9402bd0008eec9264dda4ccf458d8042a674 Mon Sep 17 00:00:00 2001
From: Adam Milligan
Date: Sat, 27 Dec 2008 13:31:58 -0800
Subject: [PATCH] The default treatment for fields with errors no longer wraps the input elements in a div, but instead adds the 'fieldWithErrors' class name directly onto the input element; added ActionView::Base#field_error_options accessor for customizing the attributes of input elements with errors.
---
.../action_view/helpers/active_record_helper.rb | 75 +++++++++++++++-----
.../test/template/active_record_helper_test.rb | 32 +++++++--
2 files changed, 81 insertions(+), 26 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..d901cc9 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -3,8 +3,11 @@ require 'action_view/helpers/form_helper'
module ActionView
class Base
- @@field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}
" }
+ @@field_error_proc = nil
cattr_accessor :field_error_proc
+
+ @@field_error_options = { :class => 'fieldWithErrors' }
+ cattr_accessor :field_error_options
end
module Helpers
@@ -246,8 +249,9 @@ module ActionView
alias_method :tag_without_error_wrapping, :tag
def tag(name, options)
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(tag_without_error_wrapping(name, options), object.errors.on(@method_name))
+ if errors?
+ options = merge_error_options(options)
+ error_wrapping(tag_without_error_wrapping(name, options))
else
tag_without_error_wrapping(name, options)
end
@@ -255,8 +259,9 @@ module ActionView
alias_method :content_tag_without_error_wrapping, :content_tag
def content_tag(name, value, options)
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(content_tag_without_error_wrapping(name, value, options), object.errors.on(@method_name))
+ if errors?
+ options = merge_error_options(options)
+ error_wrapping(content_tag_without_error_wrapping(name, value, options))
else
content_tag_without_error_wrapping(name, value, options)
end
@@ -264,8 +269,9 @@ module ActionView
alias_method :to_date_select_tag_without_error_wrapping, :to_date_select_tag
def to_date_select_tag(options = {}, html_options = {})
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(to_date_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
+ if errors?
+ html_options = merge_error_options(html_options)
+ error_wrapping(to_date_select_tag_without_error_wrapping(options, html_options))
else
to_date_select_tag_without_error_wrapping(options, html_options)
end
@@ -273,32 +279,63 @@ module ActionView
alias_method :to_datetime_select_tag_without_error_wrapping, :to_datetime_select_tag
def to_datetime_select_tag(options = {}, html_options = {})
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(to_datetime_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
- else
- to_datetime_select_tag_without_error_wrapping(options, html_options)
+ if errors?
+ html_options = merge_error_options(html_options)
+ error_wrapping(to_datetime_select_tag_without_error_wrapping(options, html_options))
+ else
+ to_datetime_select_tag_without_error_wrapping(options, html_options)
end
end
alias_method :to_time_select_tag_without_error_wrapping, :to_time_select_tag
def to_time_select_tag(options = {}, html_options = {})
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(to_time_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
+ if errors?
+ html_options = merge_error_options(html_options)
+ error_wrapping(to_time_select_tag_without_error_wrapping(options, html_options))
else
to_time_select_tag_without_error_wrapping(options, html_options)
end
end
- def error_wrapping(html_tag, has_error)
- has_error ? Base.field_error_proc.call(html_tag, self) : html_tag
+ private
+
+ def column_type
+ object.send(:column_for_attribute, @method_name).type
end
- def error_message
- object.errors.on(@method_name)
+ def errors?
+ object.respond_to?(:errors) && object.errors.respond_to?(:on) && object.errors.on(@method_name)
end
- def column_type
- object.send(:column_for_attribute, @method_name).type
+ def error_wrapping(html_tag)
+ if Base.field_error_proc
+ Base.field_error_proc.call(html_tag, self)
+ else
+ html_tag
+ end
+ end
+
+ def merge_error_options(options)
+ additive_merge(options, Base.field_error_options.stringify_keys!)
+ end
+
+ def additive_merge(lhs, rhs)
+ rhs.inject({}) do |result, (key, value)|
+ lhs_value = lhs.delete(key)
+ value = merge_values(value, lhs_value) unless lhs_value.nil?
+ result.merge(key => value)
+ end.merge(lhs)
+ end
+
+ def merge_values(lhs, rhs)
+ case lhs
+ when String
+ [lhs, rhs].join(" ")
+ when Hash
+ additive_merge(lhs, rhs)
+ else
+ lhs + rhs
+ end
end
end
end
diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb
index e46f95d..89c7c68 100644
--- a/actionpack/test/template/active_record_helper_test.rb
+++ b/actionpack/test/template/active_record_helper_test.rb
@@ -107,23 +107,41 @@ class ActiveRecordHelperTest < ActionView::TestCase
)
end
+ def test_custom_field_error_proc_properly_wraps_tag
+ old_field_error_proc = ActionView::Base.field_error_proc
+ ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag} " }
+ assert_dom_equal(
+ %( ),
+ text_area("post", "body")
+ )
+ ensure
+ ActionView::Base.field_error_proc = old_field_error_proc
+ end
+
+ def test_field_with_errors_maintains_proper_passed_in_options
+ assert_dom_equal(
+ %(),
+ text_area("post", "body", :class => "beautiful")
+ )
+ end
+
def test_text_area_with_errors
assert_dom_equal(
- %(
),
+ %(),
text_area("post", "body")
)
end
def test_text_field_with_errors
assert_dom_equal(
- %(
),
+ %( ),
text_field("post", "author_name")
)
end
def test_form_with_string
assert_dom_equal(
- %(
),
+ %(Title
\nBody Back to the hill and over it again!
),
form("post")
)
@@ -136,7 +154,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
end
assert_dom_equal(
- %(Title
\nBody
Back to the hill and over it again!
),
+ %(Title
\nBody Back to the hill and over it again!
),
form("post")
)
end
@@ -146,14 +164,14 @@ class ActiveRecordHelperTest < ActionView::TestCase
@request_forgery_protection_token = 'authenticity_token'
@form_authenticity_token = '123'
assert_dom_equal(
- %(
Title
\nBody
Back to the hill and over it again!
),
+ %(
Title
\nBody Back to the hill and over it again!
),
form("post")
)
end
def test_form_with_method_option
assert_dom_equal(
- %(Title
\nBody
Back to the hill and over it again!
),
+ %(Title
\nBody Back to the hill and over it again!
),
form("post", :method=>'get')
)
end
@@ -261,7 +279,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
def test_form_with_string_multipart
assert_dom_equal(
- %(Title
\nBody
Back to the hill and over it again!
),
+ %(Title
\nBody Back to the hill and over it again!
),
form("post", :multipart => true)
)
end
--
1.6.0