module EnhancedFormBuilder class FormBuilder < ActionView::Helpers::FormBuilder @@default_options = { :error_class => 'error', :include_errors_in_label => false, :mandatory_class => 'required', :mandatory_label => '*', :error_list_wrapper => :ul, :error_list_class => 'error_messages', :field_wrapper => :p } cattr_accessor :default_options attr_writer *default_options.keys # create accessors for all block local options # so you can set options for just a single # instance of the form as well as setting # the site wide defaults. # # form_for(@thing) do |f| # f.mandatory_class = 'arsemonkey' # end default_options.keys.each do |field| src = <<-end_src def #{field} @#{field} || default_options[:#{field}] end end_src class_eval src, __FILE__, __LINE__ end def association_select(method, options={}) # find association, call to_options on it to make the # option tags then make a regular select for method_id end # Creates a labelled_xxx alternative to all the form helpers that take an # addtional label argument: # # f.labelled_text_area 'Name', :name # # If the wrapper is specified it'll wrap the label and the field in another element, # you can also specify custom attributes for the label using :label in the option # hash. Likewise for :wrapper. # # f.labelled_text_field 'Email', :email, :class => 'boo', :label => { :class => 'thing' } # # Will give you: # #
# # It also automatically detects errors and validates_presence_of on fields and adds classes to the # field wrapper. By default require attributes will also have a * added to the label. # def self.write_label_method(field) src = <<-end_src def labelled_#{field}(label, method, options = {}) label_opts = options.delete(:label) || {} wrapper_opts = options.delete(:wrap) || {} note = options.delete(:note) || '' #{ "add_class!(options, '#{field}')" if ['text_field', 'check_box', 'radio_button', 'file_field'].include? field } add_wrapper_classes!(wrapper_opts, method) add_label_content!(label, method) wrap_field( label_for(label, method, label_opts) + ' ' + #{field}(method, options) + note, wrapper_opts.delete(:with), wrapper_opts) end end_src class_eval src, __FILE__, __LINE__ end %w{text_field text_area select check_box radio_button file_field association_select password_field country_select}.each { |field| write_label_method field } # Outputs for errors in a more easily customisable way. # # <% f.errors :wrap => :div, :class => 'beebo' do |field, message| %> # <%= field %. <%= message %>