Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,14 @@ following the convention in Rails. You can also specify `include_hidden: false`

Any extra option passed to these methods will be rendered as html option.

Error messages are HTML-escaped by default. If you need to render HTML in error messages
(e.g. links), mark them as `html_safe`. This works for both custom error messages and
model validation messages automatically added to inputs:

```erb
<%= f.error :name, error: 'please see <a href="/help">our guide</a>'.html_safe %>
```

### Stripping away all wrapper divs

**Simple Form** also allows you to strip away all the div wrappers around the `<input>` field that is
Expand Down
10 changes: 10 additions & 0 deletions lib/simple_form/form_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,15 @@ def button(type, *args, &block)
# Creates an error tag based on the given attribute, only when the attribute
# contains errors. All the given options are sent as :error_html.
#
# Error messages are HTML-escaped by default. Messages marked as +html_safe+
# will be rendered without escaping.
#
# == Examples
#
# f.error :name
# f.error :name, id: "cool_error"
# f.error :name, error: "custom error message"
# f.error :name, error: "see <a href='/help'>our guide</a>".html_safe
#
def error(attribute_name, options = {})
options = options.dup
Expand All @@ -266,9 +271,14 @@ def error(attribute_name, options = {})
# Return the error but also considering its name. This is used
# when errors for a hidden field need to be shown.
#
# Error messages are HTML-escaped by default. Messages marked as +html_safe+
# will be rendered without escaping.
#
# == Examples
#
# f.full_error :token #=> <span class="error">Token is invalid</span>
# f.full_error :token, error: "custom error message"
# f.full_error :token, error: "see <a href='/help'>our guide</a>".html_safe
#
def full_error(attribute_name, options = {})
options = options.dup
Expand Down
68 changes: 62 additions & 6 deletions test/form_builder/error_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,26 +86,55 @@ def with_full_error_for(object, *args)
assert_no_select 'p.error[error_method]'
end

test 'error escapes error prefix text' do
with_error_for @user, :name, error_prefix: '<b>Name</b>'
assert_no_select 'span.error b'
end

test 'error escapes error text' do
@user.errors.add(:action, 'must not contain <b>markup</b>')

with_error_for @user, :action

assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end

test 'error does not escape error text marked as safe' do
@user.errors.add(:action, 'must have a <a href="/help">valid format</a>'.html_safe)
with_error_for @user, :action

assert_select 'span.error'
assert_select 'span.error a', 'valid format'
end

test 'error escapes error prefix text' do
with_error_for @user, :name, error_prefix: '<b>Name</b>'

assert_no_select 'span.error b'
end

test 'error generates an error message with raw HTML tags' do
with_error_for @user, :name, error_prefix: '<b>Name</b>'.html_safe

assert_select 'span.error', "Name cannot be blank"
assert_select 'span.error b', "Name"
end

test 'error accepts a custom error message via error option' do
with_error_for @user, :name, error: 'must be unique'

assert_select 'span.error', 'must be unique'
end

test 'error escapes custom error message via error option' do
with_error_for @user, :name, error: 'must not contain <b>markup</b>'

assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end

test 'error does not escape custom error message via error option marked as safe' do
with_error_for @user, :name, error: 'must have a <a href="/help">valid format</a>'.html_safe

assert_select 'span.error'
assert_select 'span.error a', 'valid format'
end

test 'error adds aria-invalid attribute to inputs' do
with_form_for @user, :name, error: true
assert_select "input#user_name[name='user[name]'][aria-invalid='true']"
Expand Down Expand Up @@ -156,13 +185,40 @@ def with_full_error_for(object, *args)

test 'full error escapes error text' do
@user.errors.add(:action, 'must not contain <b>markup</b>')
with_full_error_for @user, :action

assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end

test 'full error does not escape error text marked as safe' do
@user.errors.add(:action, 'must have a <a href="/help">valid format</a>'.html_safe)
with_full_error_for @user, :action

assert_select 'span.error'
assert_select 'span.error a', 'valid format'
end

test 'full error accepts a custom error message via error option' do
with_full_error_for @user, :name, error: 'must be unique'

assert_select 'span.error', 'Super User Name! must be unique'
end

test 'full error escapes custom error message via error option' do
with_full_error_for @user, :name, error: 'must not contain <b>markup</b>'

assert_select 'span.error'
assert_no_select 'span.error b', 'markup'
end

test 'full error does not escape custom error message via error option marked as safe' do
with_full_error_for @user, :name, error: 'must have a <a href="/help">valid format</a>'.html_safe

assert_select 'span.error'
assert_select 'span.error a', 'valid format'
end

test 'full error uses human_attribute_name and passed object as an option to it' do
@user.errors.add(:status, 'error')
with_full_error_for @user, :status
Expand Down
Loading