mirror of https://github.com/rails/rails
Execute `field_error_proc` within view
Instead of treating it as an anonymous block, execute the `ActionView::Base.field_error_proc` within the context of the `ActionView::Base` instance. This enables consumer applications to continue to override the proc as they see fit, but frees them from declaring templating logic within a `config/initializers/*.rb`, `config/environments/*.rb` or `config/application.rb` file. This makes it possible to replace something like: ```ruby config.action_view.field_error_proc = proc do |html_tag, instance| <<~HTML.html_safe #{html_tag} <span class="errors">#{instance.error_message.to_sentence}</span> HTML end ``` With inline calls to Action View helpers like: ```ruby config.action_view.field_error_proc = proc do |html_tag, instance| safe_join [ html_tag, tag.span(instance.error_message.to_sentence, class: "errors") ] end ``` Or with a view partial rendering, like: ```ruby config.action_view.field_error_proc = proc do |html_tag, instance| render partial: "application/field_with_errors", locals: { html_tag: html_tag, instance: instance } end ``` Then, elsewhere in `app/views/application/field_with_errors.html.erb`: ```erb <%= html_tag %> <span class="errors"><%= instance.error_message.to_sentence %></span> ```
This commit is contained in:
parent
9f980664fc
commit
9c86593caa
|
@ -1,3 +1,12 @@
|
|||
* Execute the `ActionView::Base.field_error_proc` within the context of the
|
||||
`ActionView::Base` instance:
|
||||
|
||||
```ruby
|
||||
config.action_view.field_error_proc = proc { |html| content_tag(:div, html, class: "field_with_errors") }
|
||||
```
|
||||
|
||||
*Sean Doyle*
|
||||
|
||||
* Add `:day_format` option to `date_select`
|
||||
|
||||
date_select("article", "written_on", day_format: ->(day) { day.ordinalize })
|
||||
|
|
|
@ -142,7 +142,7 @@ module ActionView # :nodoc:
|
|||
include Helpers, ::ERB::Util, Context
|
||||
|
||||
# Specify the proc used to decorate input tags that refer to attributes with errors.
|
||||
cattr_accessor :field_error_proc, default: Proc.new { |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }
|
||||
cattr_accessor :field_error_proc, default: Proc.new { |html_tag, instance| content_tag :div, html_tag, class: "field_with_errors" }
|
||||
|
||||
# How to complete the streaming when an exception occurs.
|
||||
# This is our best guess: first try to close the attribute, then the tag.
|
||||
|
|
|
@ -27,7 +27,7 @@ module ActionView
|
|||
|
||||
def error_wrapping(html_tag)
|
||||
if object_has_errors?
|
||||
Base.field_error_proc.call(html_tag, self)
|
||||
@template_object.instance_exec(html_tag, self, &Base.field_error_proc)
|
||||
else
|
||||
html_tag
|
||||
end
|
||||
|
|
|
@ -33,6 +33,12 @@ module Fun
|
|||
end
|
||||
end
|
||||
|
||||
class ValidatingPost < Post
|
||||
include ActiveModel::Validations
|
||||
|
||||
validates :title, presence: true
|
||||
end
|
||||
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
|
@ -487,6 +493,14 @@ class TestController < ActionController::Base
|
|||
render partial: ActionView::Helpers::FormBuilder.new(:post, nil, view_context, {})
|
||||
end
|
||||
|
||||
def partial_with_form_builder_and_invalid_model
|
||||
post = ValidatingPost.new
|
||||
|
||||
post.validate
|
||||
|
||||
render partial: ActionView::Helpers::FormBuilder.new(:post, post, view_context, {})
|
||||
end
|
||||
|
||||
def partial_with_form_builder_subclass
|
||||
render partial: LabellingFormBuilder.new(:post, nil, view_context, {})
|
||||
end
|
||||
|
@ -680,6 +694,7 @@ class RenderTest < ActionController::TestCase
|
|||
get :partial_only, to: "test#partial_only"
|
||||
get :partial_with_counter, to: "test#partial_with_counter"
|
||||
get :partial_with_form_builder, to: "test#partial_with_form_builder"
|
||||
get :partial_with_form_builder_and_invalid_model, to: "test#partial_with_form_builder_and_invalid_model"
|
||||
get :partial_with_form_builder_subclass, to: "test#partial_with_form_builder_subclass"
|
||||
get :partial_with_hash_object, to: "test#partial_with_hash_object"
|
||||
get :partial_with_locals, to: "test#partial_with_locals"
|
||||
|
@ -1300,6 +1315,44 @@ class RenderTest < ActionController::TestCase
|
|||
assert_equal "<label for=\"post_title\">Title</label>\n", @response.body
|
||||
end
|
||||
|
||||
def test_partial_with_form_builder_and_invalid_model
|
||||
get :partial_with_form_builder_and_invalid_model
|
||||
|
||||
assert_equal <<~HTML.strip, @response.body.strip
|
||||
<div class="field_with_errors"><label for="post_title">Title</label></div>
|
||||
HTML
|
||||
end
|
||||
|
||||
def test_partial_with_form_builder_and_invalid_model_custom_field_error_proc
|
||||
old_proc = ActionView::Base.field_error_proc
|
||||
ActionView::Base.field_error_proc = proc { |html| tag.div html, class: "errors" }
|
||||
|
||||
get :partial_with_form_builder_and_invalid_model
|
||||
|
||||
assert_equal <<~HTML.strip, @response.body.strip
|
||||
<div class="errors"><label for="post_title">Title</label></div>
|
||||
HTML
|
||||
ensure
|
||||
ActionView::Base.field_error_proc = old_proc if old_proc
|
||||
end
|
||||
|
||||
def test_partial_with_form_builder_and_invalid_model_custom_rendering_field_error_proc
|
||||
old_proc = ActionView::Base.field_error_proc
|
||||
ActionView::Base.field_error_proc = proc do |html_tag, instance|
|
||||
render inline: <<~ERB, locals: { html_tag: html_tag, instance: instance }
|
||||
<div class="field_with_errors"><%= html_tag %> <span class="error"><%= [instance.error_message].join(', ') %></span></div>
|
||||
ERB
|
||||
end
|
||||
|
||||
get :partial_with_form_builder_and_invalid_model
|
||||
|
||||
assert_equal <<~HTML.strip, @response.body.strip
|
||||
<div class="field_with_errors"><label for="post_title">Title</label> <span class="error">can't be blank</span></div>
|
||||
HTML
|
||||
ensure
|
||||
ActionView::Base.field_error_proc = old_proc if old_proc
|
||||
end
|
||||
|
||||
def test_partial_with_form_builder_subclass
|
||||
get :partial_with_form_builder_subclass
|
||||
assert_equal "<label for=\"post_title\">Title</label>\n", @response.body
|
||||
|
|
|
@ -1083,6 +1083,14 @@ Controls whether or not templates should be reloaded on each request. Defaults t
|
|||
|
||||
#### `config.action_view.field_error_proc`
|
||||
|
||||
* `config.action_view.field_error_proc` provides an HTML generator for
|
||||
displaying errors that come from Active Model. The block is evaluated within
|
||||
the context of an Action View template. The default is
|
||||
|
||||
```ruby
|
||||
Proc.new { |html_tag, instance| content_tag :div, html_tag, class: "field_with_errors" }
|
||||
```
|
||||
|
||||
Provides an HTML generator for displaying errors that come from Active Model. The default is
|
||||
|
||||
```ruby
|
||||
|
|
Loading…
Reference in New Issue