Class: FormSan::FormBuilder

Inherits:
ActionView::Helpers::FormBuilder
  • Object
show all
Defined in:
lib/form_san.rb

Overview

FormSan::FormBuilder

FormSan has two goals:

  • Make it easier for the developer to write out a form

  • Make the resulting form more usable

You can use the form builder by specifying it in the :builder option in form_for.

form_for(@post, :builder => FormSan::FormBuilder)

You can also make it the default form builder by specifying it in an initializer or environment.rb.

ActionView::Base.default_form_builder = FormSan::FormBuilder

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#templateObject (readonly)

Returns the value of attribute template.



18
19
20
# File 'lib/form_san.rb', line 18

def template
  @template
end

Instance Method Details

#error_message(attribute) ⇒ Object

Generates a short in a paragraph with the validation error of a specific attribute.

<%= f.error_message(:title) %>

Generates something like

<p class="notice">Can't be blank</p>


86
87
88
89
90
91
92
93
94
# File 'lib/form_san.rb', line 86

def error_message(attribute)
  unless @object.errors.on(attribute).blank?
    (:p, :class => 'notice') do
      concat ERB::Util.html_escape(@object.errors.on(attribute).mb_chars.capitalize)
    end
  else
    ''
  end
end

#error_messagesObject

Generates a short sentence in a paragraph describing which attributes have validation errors.

<%= f.error_messages %>

Generates something like

<p class="errors">Sorry, there were problems with the title, published date, and description.</p>


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/form_san.rb', line 62

def error_messages
  unless @object.errors.count.zero?
    attributes_with_errors =  @object.errors.map { |attribute, _| attribute } - ['base']
    (:p, :class => 'errors') do
      if attributes_with_errors.size > 1
        concat "Sorry, there were problems with the #{attributes_with_errors.to_sentence}."
      elsif attributes_with_errors.size == 1
        concat "Sorry, there was a problem with the #{attributes_with_errors.first}."
      else
        concat "#{@object.class} #{@object.errors.on(:base)}."
      end
    end
  else
    ''
  end
end

#field(attribute, *args, &block) ⇒ Object

Generates a field of a certain type wrapped in all sorts of HTML.

<%= f.field(:title, :type => :text) %>
<div class="field">
  <div class="label"><label for="book_title">Title</label></div>
  <input id="book_title" type="text" name="book[title]" value="Empire of the Sun" />
</div>

When there is a validation error on the attribute, this will also be reflected in the HTML.

<div class="invalid field">
  <div class="label"><label for="book_title">Title</label></div>
  <input id="book_title" type="text" name="book[title]" value="" />
  <p class="notice">Can't be blank.</p>
</div>

You can also pass a block to field, that way you can include more HTML into the div.

<% f.field(:title, :type => :text) do %>
  <p class="note">This will be shown on the overview page as the book title.</p>
<% end %>

<div class="field">
  <div class="label"><label for="book_title">Title</label></div>
  <input id="book_title" type="text" name="book[title]" value="Empire of the Sun" />
  <p class="note">This will be shown on the overview page as the book title.</p>
</div>

All options except :type are passed to the input.

<%= f.field(:title, :type => :text, :class => 'small') %>

<div class="field">
  <div class="label"><label for="book_title">Title</label></div>
  <input id="book_title" type="text" name="book[title]" value="Empire of the Sun" class="small" />
</div>


182
183
184
185
186
187
188
# File 'lib/form_san.rb', line 182

def field(attribute, *args, &block)
  if block_given?
    concat field_with_extra_content(attribute, @template.capture(&block), *args)
  else
    field_with_extra_content(attribute, nil, *args)
  end
end

#field_with_extra_content(attribute, extra_content = nil, *args) ⇒ Object

:nodoc:



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/form_san.rb', line 127

def field_with_extra_content(attribute, extra_content=nil, *args) #:nodoc:
  options = args.extract_options!
  classes = @object.errors.on(attribute) ? 'invalid field' : 'field'
  
  (:div, :class => classes) do
    concat wrapped_label(attribute, args.first, :optional => options.delete(:optional))
    
    case input_type = options.delete(:type).to_s
    when 'textarea'
      concat ActionView::Helpers::InstanceTag.new(@object_name, attribute, self, @object).to_text_area_tag(options)
    else
      concat ActionView::Helpers::InstanceTag.new(@object_name, attribute, self, @object).to_input_field_tag(input_type, options)
    end
    
    concat extra_content unless extra_content.blank?
    @template.output_buffer # The block needs to return the current buffer
  end
end

#fields(&block) ⇒ Object

Wraps its content in a div with a fields class. You use it to group fields.

<% f.fields do %>
  <h4>Personal information</h4>
  …
<% end %>

Generates

<div class="fields">
  <h4>Personal information</h4>
  …
</div>


51
52
53
# File 'lib/form_san.rb', line 51

def fields(&block)
  (:div, :class => 'fields', &block)
end

#fieldset(&block) ⇒ Object

Wraps its content in a div with a fieldset class. You use it to group sets of fields.

<% f.fieldset do %>
  <p>Please complete the form.</p>
  …
<% end %>

Generates

<div class="fieldset">
  <p>Please complete the form.</p>
  …
</div>


34
35
36
# File 'lib/form_san.rb', line 34

def fieldset(&block)
  (:div, :class => 'fieldset', &block)
end

#wrapped_label(attribute, *args) ⇒ Object

Generates a label for an attribute wrapped in a div. It allows you to specify an alternative humanized form of the attribute name and whether the associated field is optional or not.

<%= f.label(:title) %>
<div class="label"><label for="book_title">Title</label></div>

<%= f.label(:title, 'Book title') %>
<div class="label"><label for="book_title">Book title</label></div>

<%= f.label(:title, :optional => true) %>
<div class="label"><label for="book_title">Title <span>(optional)</span></label></div>

When there is a validation error on the attribute, this will also be reflected in the HTML.

<%= f.label(:title) %>
<div class="label">
  <label for="book_title">Title <span>(optional)</span></label>
  <p class="notice">Can't be blank.</p>
</div>


115
116
117
118
119
120
121
122
123
124
125
# File 'lib/form_san.rb', line 115

def wrapped_label(attribute, *args)
  options = args.extract_options!
  
  label_text = args.first || attribute.to_s.humanize
  label_text << ' <span>(optional)</span>' if options[:optional]
  
  (:div, :class => 'label') do
    concat label(attribute, label_text)
    concat error_message(attribute)
  end
end