Skip to content
This repository has been archived by the owner on Oct 12, 2019. It is now read-only.

Commit

Permalink
Adding bootstrap-friendly "semantic_errors" helper (and accompanying
Browse files Browse the repository at this point in the history
passing spec)
  • Loading branch information
nzaillian committed Apr 4, 2013
1 parent d87b86c commit 057f708
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/formtastic-bootstrap/form_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def self.default_hint_class=(hint_class)

include FormtasticBootstrap::Helpers::InputHelper # Revisit
include FormtasticBootstrap::Helpers::InputsHelper
include FormtasticBootstrap::Helpers::ErrorsHelper
include FormtasticBootstrap::Helpers::ActionHelper
include FormtasticBootstrap::Helpers::ActionsHelper
# include Formtastic::Helpers::ErrorsHelper
Expand Down
70 changes: 70 additions & 0 deletions lib/formtastic-bootstrap/helpers/errors_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module FormtasticBootstrap
module Helpers
module ErrorsHelper
include Formtastic::Helpers::FileColumnDetection
include Formtastic::Helpers::Reflection
include Formtastic::LocalizedString

INLINE_ERROR_TYPES = [:sentence, :list, :first]

# Generates a bootstrap error alert element containing
# an unordered list of error messages on the base object and optionally for a given
# set of named attribute. This is idea for rendering a block of error messages at the top of
# the form for hidden/special/virtual attributes (the Paperclip Rails plugin does this), or
# errors on the base model.
#
# A hash can be used as the last set of arguments to pass HTML attributes to the `<ul>`
# wrapper.
#
# @example A list of errors on the base model
# <%= semantic_form_for ... %>
# <%= f.semantic_errors %>
# ...
# <% end %>
#
# @example A list of errors on the base and named attributes
# <%= semantic_form_for ... %>
# <%= f.semantic_errors :something_special %>
# ...
# <% end %>
#
# @example A list of errors on the base model, with custom HTML attributes
# <%= semantic_form_for ... %>
# <%= f.semantic_errors :class => "awesome" %>
# ...
# <% end %>
#
# @example A list of errors on the base model and named attributes, with custom HTML attributes
# <%= semantic_form_for ... %>
# <%= f.semantic_errors :something_special, :something_else, :class => "awesome", :onclick => "Awesome();" %>
# ...
# <% end %>
def semantic_errors(*args)
html_options = args.extract_options!
args = args - [:base]
full_errors = args.inject([]) do |array, method|
attribute = localized_string(method, method.to_sym, :label) || humanized_attribute_name(method)
errors = Array(@object.errors[method.to_sym]).to_sentence
errors.present? ? array << [attribute, errors].join(" ") : array ||= []
end
full_errors << @object.errors[:base]
full_errors.flatten!
full_errors.compact!
return nil if full_errors.blank?

if html_options[:class].blank?
html_options[:class] = "alert alert-error"
else
html_options[:class] = "alert alert-error " + html_options[:class]
end

template.content_tag(:div, html_options) do
template.content_tag(:button, "&times;".html_safe, :class => "close", "data-dismiss" => "alert") +
template.content_tag(:ul, {class: "error-list"}) do

This comment has been minimized.

Copy link
@owocki

owocki Jun 13, 2013

i'm not sure if it's because i'm a rails noob or not, but im getting a syntax error here

/Library/Ruby/Gems/1.8/gems/formtastic-bootstrap-2.1.1/lib/formtastic-bootstrap/form_builder.rb:34: /Library/Ruby/Gems/1.8/gems/formtastic-bootstrap-2.1.1/lib/formtastic-bootstrap/helpers/errors_helper.rb:63: syntax error, unexpected ':' (SyntaxError)
          template.content_tag(:ul, {class: "error-list"}) do
                                           ^
/Library/Ruby/Gems/1.8/gems/formtastic-bootstrap-2.1.1/lib/formtastic-bootstrap/helpers/errors_helper.rb:63: syntax error, unexpected '}', expecting kEND
          template.content_tag(:ul, {class: "error-list"}) do
                                                         ^
/Library/Ruby/Gems/1.8/gems/formtastic-bootstrap-2.1.1/lib/formtastic-bootstrap/helpers/errors_helper.rb:70: syntax error, unexpected kEND, expecting $end
    from /Library/Ruby/Gems/1.8/gems/formtastic-bootstrap-2.1.1/lib/formtastic-bootstrap.rb:4:in `require'
    from /Library/Ruby/Gems/1.8/gems/formtastic-bootstrap-2.1.1/lib/formtastic-bootstrap.rb:4
    from /Library/Ruby/Gems/1.8/gems/bundler-1.1.5/lib/bundler/runtime.rb:68:in `require'
    from /Library/Ruby/Gems/1.8/gems/bundler-1.1.5/lib/bundler/runtime.rb:68:in `require'
    from /Library/Ruby/Gems/1.8/gems/bundler-1.1.5/lib/bundler/runtime.rb:66:in `each'
    from /Library/Ruby/Gems/1.8/gems/bundler-1.1.5/lib/bundler/runtime.rb:66:in `require'
    from /Library/Ruby/Gems/1.8/gems/bundler-1.1.5/lib/bundler/runtime.rb:55:in `each'
    from /Library/Ruby/Gems/1.8/gems/bundler-1.1.5/lib/bundler/runtime.rb:55:in `require'
    from /Library/Ruby/Gems/1.8/gems/bundler-1.1.5/lib/bundler.rb:119:in `require'
    from /Users/kevinowocki/Sites/slowordown/config/application.rb:7
    from /Library/Ruby/Gems/1.8/gems/railties-3.2.13/lib/rails/commands.rb:53:in `require'
    from /Library/Ruby/Gems/1.8/gems/railties-3.2.13/lib/rails/commands.rb:53
    from /Library/Ruby/Gems/1.8/gems/railties-3.2.13/lib/rails/commands.rb:50:in `tap'
    from /Library/Ruby/Gems/1.8/gems/railties-3.2.13/lib/rails/commands.rb:50
    from script/rails:6:in `require'
    from script/rails:6

Rails 3.2.13

This comment has been minimized.

Copy link
@sodabrew

sodabrew Jun 13, 2013

Collaborator

This is Ruby 1.9 syntax. Pushing a fix right now so that it will run on Ruby 1.8.

This comment has been minimized.

Copy link
@sodabrew

sodabrew Jun 13, 2013

Collaborator

Fixed in version 2.1.3, just posted to Rubygems.

This comment has been minimized.

Copy link
@owocki

owocki Jun 13, 2013

you'z a boss. thanks.

Formtastic::Util.html_safe(full_errors.map { |error| template.content_tag(:li, Formtastic::Util.html_safe(error)) }.join)
end
end
end
end
end
end
112 changes: 112 additions & 0 deletions spec/helpers/semantic_errors_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# encoding: utf-8
require 'spec_helper'

describe 'FormtasticBootstrap::FormBuilder#semantic_errors' do

include FormtasticSpecHelper

before do
@output_buffer = ''
mock_everything
@title_errors = ['must not be blank', 'must be awesome']
@base_errors = ['base error message', 'nasty error']
@base_error = 'one base error'
@errors = mock('errors')
@new_post.stub!(:errors).and_return(@errors)
end

describe 'when there is only one error on base' do
before do
@errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
end

it 'should render an alert with an unordered list' do
semantic_form_for(@new_post) do |builder|
builder.semantic_errors.should have_tag('.alert.alert-error ul.error-list li', @base_error)
end
end
end

describe 'when there is more than one error on base' do
before do
@errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_errors)
end

it 'should render an unordered list' do
semantic_form_for(@new_post) do |builder|
builder.semantic_errors.should have_tag('.alert.alert-error ul.error-list')
@base_errors.each do |error|
builder.semantic_errors.should have_tag('.alert.alert-error ul.error-list li', error)
end
end
end
end

describe 'when there are errors on title' do
before do
@errors.stub!(:[]).with(errors_matcher(:title)).and_return(@title_errors)
@errors.stub!(:[]).with(errors_matcher(:base)).and_return([])
end

it 'should render an unordered list' do
semantic_form_for(@new_post) do |builder|
title_name = builder.send(:localized_string, :title, :title, :label) || builder.send(:humanized_attribute_name, :title)
builder.semantic_errors(:title).should have_tag('.alert.alert-error ul.error-list li', title_name << " " << @title_errors.to_sentence)
end
end
end

describe 'when there are errors on title and base' do
before do
@errors.stub!(:[]).with(errors_matcher(:title)).and_return(@title_errors)
@errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
end

it 'should render an unordered list' do
semantic_form_for(@new_post) do |builder|
title_name = builder.send(:localized_string, :title, :title, :label) || builder.send(:humanized_attribute_name, :title)
builder.semantic_errors(:title).should have_tag('.alert.alert-error ul.error-list li', title_name << " " << @title_errors.to_sentence)
builder.semantic_errors(:title).should have_tag('.alert.alert-error ul.error-list li', @base_error)
end
end
end

describe 'when there are no errors' do
before do
@errors.stub!(:[]).with(errors_matcher(:title)).and_return(nil)
@errors.stub!(:[]).with(errors_matcher(:base)).and_return(nil)
end

it 'should return nil' do
semantic_form_for(@new_post) do |builder|
builder.semantic_errors(:title).should be_nil
end
end
end

describe 'when there is one error on base and options with class is passed' do
before do
@errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
end

it 'should render an unordered list with given class' do
semantic_form_for(@new_post) do |builder|
builder.semantic_errors(:class => "awesome").should have_tag('.alert.alert-error.awesome ul.error-list li', @base_error)
end
end
end

describe 'when :base is passed in as an argument' do
before do
@errors.stub!(:[]).with(errors_matcher(:base)).and_return(@base_error)
end

it 'should ignore :base and only render base errors once' do
semantic_form_for(@new_post) do |builder|
builder.semantic_errors(:base).should have_tag('ul li', :count => 1)
builder.semantic_errors(:base).should_not have_tag('ul li', "Base #{@base_error}")
end
end
end

end
4 changes: 4 additions & 0 deletions vendor/assets/stylesheets/formtastic-bootstrap.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.hidden {
display: none;
}

.alert.alert-error .error-list {
margin: 0px;
}

3 comments on commit 057f708

@djwonk
Copy link

@djwonk djwonk commented on 057f708 Apr 10, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit causes the specs to halt (not just fail).

bundle exec rake spec

formtastic-bootstrap/lib/formtastic-bootstrap/form_builder.rb:34:in `<class:FormBuilder>': uninitialized constant FormtasticBootstrap::Helpers::ErrorsHelper (NameError)
  from /Users/david/src/formtastic-bootstrap/lib/formtastic-bootstrap/form_builder.rb:3:in `<module:FormtasticBootstrap>'
  from /Users/david/src/formtastic-bootstrap/lib/formtastic-bootstrap/form_builder.rb:1:in `<top (required)>'
  from /Users/david/src/formtastic-bootstrap/lib/formtastic-bootstrap.rb:4:in `<top (required)>'

@nzaillian
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into it right now

@djwonk
Copy link

@djwonk djwonk commented on 057f708 Apr 10, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My pull request is here: #64

Please sign in to comment.