padrino-helpers 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/padrino-helpers.rb +4 -1
- data/lib/padrino-helpers/asset_tag_helpers.rb +17 -14
- data/lib/padrino-helpers/breadcrumb_helpers.rb +6 -6
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +119 -163
- data/lib/padrino-helpers/form_builder/deprecated_builder_methods.rb +92 -0
- data/lib/padrino-helpers/form_helpers.rb +66 -347
- data/lib/padrino-helpers/form_helpers/errors.rb +138 -0
- data/lib/padrino-helpers/form_helpers/options.rb +97 -0
- data/lib/padrino-helpers/form_helpers/security.rb +70 -0
- data/lib/padrino-helpers/output_helpers.rb +1 -1
- data/lib/padrino-helpers/output_helpers/abstract_handler.rb +1 -1
- data/lib/padrino-helpers/render_helpers.rb +10 -9
- data/lib/padrino-helpers/tag_helpers.rb +2 -1
- data/lib/padrino/rendering.rb +378 -0
- data/lib/padrino/rendering/extensions/erubis.rb +74 -0
- data/lib/padrino/rendering/extensions/haml.rb +29 -0
- data/lib/padrino/rendering/extensions/slim.rb +21 -0
- data/padrino-helpers.gemspec +2 -1
- data/test/fixtures/apps/.components +6 -0
- data/test/fixtures/apps/.gitignore +7 -0
- data/test/fixtures/apps/render.rb +25 -0
- data/test/fixtures/apps/views/article/comment/show.slim +1 -0
- data/test/fixtures/apps/views/blog/post.erb +1 -0
- data/test/fixtures/apps/views/layouts/specific.erb +1 -0
- data/test/fixtures/apps/views/test/post.erb +1 -0
- data/test/fixtures/layouts/layout.erb +1 -0
- data/test/fixtures/markup_app/app.rb +0 -1
- data/test/fixtures/render_app/app.rb +25 -1
- data/test/fixtures/render_app/views/_unsafe.html.builder +2 -0
- data/test/fixtures/render_app/views/_unsafe_object.html.builder +2 -0
- data/test/fixtures/render_app/views/ruby_block_capture_erb.erb +1 -0
- data/test/fixtures/render_app/views/ruby_block_capture_haml.haml +1 -0
- data/test/fixtures/render_app/views/ruby_block_capture_slim.slim +1 -0
- data/test/helper.rb +65 -1
- data/test/test_asset_tag_helpers.rb +83 -79
- data/test/test_breadcrumb_helpers.rb +20 -20
- data/test/test_form_builder.rb +196 -196
- data/test/test_form_helpers.rb +163 -163
- data/test/test_format_helpers.rb +65 -65
- data/test/test_locale.rb +1 -1
- data/test/test_number_helpers.rb +10 -11
- data/test/test_output_helpers.rb +28 -28
- data/test/test_render_helpers.rb +89 -35
- data/test/test_rendering.rb +683 -0
- data/test/test_rendering_extensions.rb +14 -0
- data/test/test_tag_helpers.rb +23 -23
- metadata +57 -5
| @@ -0,0 +1,92 @@ | |
| 1 | 
            +
            module Padrino
         | 
| 2 | 
            +
              module Helpers
         | 
| 3 | 
            +
                module FormBuilder
         | 
| 4 | 
            +
                  module DeprecatedBuilderMethods
         | 
| 5 | 
            +
                    ##
         | 
| 6 | 
            +
                    # Returns true if the value matches the value in the field.
         | 
| 7 | 
            +
                    # field_has_value?(:gender, 'male')
         | 
| 8 | 
            +
                    def values_matches_field?(field, value)
         | 
| 9 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 10 | 
            +
                      value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    ##
         | 
| 14 | 
            +
                    # Add a :invalid css class to the field if it contain an error.
         | 
| 15 | 
            +
                    #
         | 
| 16 | 
            +
                    def field_error(field, options)
         | 
| 17 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 18 | 
            +
                      error = @object.errors[field] rescue nil
         | 
| 19 | 
            +
                      error.blank? ? options[:class] : [options[:class], :invalid].flatten.compact.join(" ")
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    def nested_form?
         | 
| 23 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 24 | 
            +
                      @options[:nested] && @options[:nested][:parent] && @options[:nested][:parent].respond_to?(:object)
         | 
| 25 | 
            +
                      is_nested && object.respond_to?(:new_record?) && !object.new_record? && object.id
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    ##
         | 
| 29 | 
            +
                    # Returns a new record of the type specified in the object
         | 
| 30 | 
            +
                    #
         | 
| 31 | 
            +
                    def build_object(object_or_symbol)
         | 
| 32 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 33 | 
            +
                      object_or_symbol.is_a?(Symbol) ? @template.instance_variable_get("@#{object_or_symbol}") || object_class(object_or_symbol).new : object_or
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    ##
         | 
| 37 | 
            +
                    # Returns the object's models name.
         | 
| 38 | 
            +
                    #
         | 
| 39 | 
            +
                    def object_model_name(explicit_object=object)
         | 
| 40 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 41 | 
            +
                      return @options[:as] if root_form? && @options[:as].is_a?(Symbol)
         | 
| 42 | 
            +
                      explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(/\//, '_')
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    ##
         | 
| 46 | 
            +
                    # Returns the class type for the given object.
         | 
| 47 | 
            +
                    #
         | 
| 48 | 
            +
                    def object_class(explicit_object)
         | 
| 49 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 50 | 
            +
                      explicit_object.is_a?(Symbol) ? explicit_object.to_s.camelize.constantize : explicit_object.class
         | 
| 51 | 
            +
                      @object.respond_to?(field) ? @object.send(field) : ''
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    ##
         | 
| 55 | 
            +
                    # Returns true if this form is the top-level (not nested).
         | 
| 56 | 
            +
                    # Returns a record from template instance or create a record of specified class.
         | 
| 57 | 
            +
                    #
         | 
| 58 | 
            +
                    def root_form?
         | 
| 59 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 60 | 
            +
                      !nested_form?
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    def build_object(symbol)
         | 
| 64 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 65 | 
            +
                      @template.instance_variable_get("@#{symbol}") || symbol.to_s.camelize.constantize.new
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    def field_result
         | 
| 69 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 70 | 
            +
                      result = []
         | 
| 71 | 
            +
                      result << object_model_name if root_form?
         | 
| 72 | 
            +
                      result
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    def merge_default_options!(field, options)
         | 
| 76 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 77 | 
            +
                      options.reverse_merge!(:value => field_value(field), :id => field_id(field))
         | 
| 78 | 
            +
                      options.merge!(:class => field_error(field, options))
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    def result_options
         | 
| 82 | 
            +
                      logger.warn "##{__method__} is deprecated"
         | 
| 83 | 
            +
                      {
         | 
| 84 | 
            +
                        :parent_form  => @options[:nested][:parent],
         | 
| 85 | 
            +
                        :nested_index => @options[:nested][:index],
         | 
| 86 | 
            +
                        :attributes_name => "#{@options[:nested][:association]}_attributes"
         | 
| 87 | 
            +
                      }
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
            end
         | 
| @@ -1,4 +1,6 @@ | |
| 1 | 
            -
            require ' | 
| 1 | 
            +
            require 'padrino-helpers/form_helpers/errors'
         | 
| 2 | 
            +
            require 'padrino-helpers/form_helpers/options'
         | 
| 3 | 
            +
            require 'padrino-helpers/form_helpers/security'
         | 
| 2 4 |  | 
| 3 5 | 
             
            module Padrino
         | 
| 4 6 | 
             
              module Helpers
         | 
| @@ -6,6 +8,12 @@ module Padrino | |
| 6 8 | 
             
                # Helpers related to producing form related tags and inputs into templates.
         | 
| 7 9 | 
             
                #
         | 
| 8 10 | 
             
                module FormHelpers
         | 
| 11 | 
            +
                  def self.included(base)
         | 
| 12 | 
            +
                    base.send(:include, FormHelpers::Errors)
         | 
| 13 | 
            +
                    base.send(:include, FormHelpers::Options)
         | 
| 14 | 
            +
                    base.send(:include, FormHelpers::Security)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 9 17 | 
             
                  ##
         | 
| 10 18 | 
             
                  # Constructs a form for object using given or default form_builder.
         | 
| 11 19 | 
             
                  #
         | 
| @@ -13,7 +21,7 @@ module Padrino | |
| 13 21 | 
             
                  #   The object for which the form is being built.
         | 
| 14 22 | 
             
                  # @param [String] URL
         | 
| 15 23 | 
             
                  #   The url this form will submit to.
         | 
| 16 | 
            -
                  # @param [Hash]  | 
| 24 | 
            +
                  # @param [Hash] options
         | 
| 17 25 | 
             
                  #   The settings associated with this form.
         | 
| 18 26 | 
             
                  #   Accepts a :namespace option that will be prepended to the id attributes of the form's elements.
         | 
| 19 27 | 
             
                  #   Also accepts HTML options.
         | 
| @@ -33,13 +41,12 @@ module Padrino | |
| 33 41 | 
             
                  #   form_for @user, '/register', :id => 'register' do |f| ... end
         | 
| 34 42 | 
             
                  #   form_for @user, '/register', :as => :customer do |f| ... end
         | 
| 35 43 | 
             
                  #
         | 
| 36 | 
            -
                  def form_for(object, url,  | 
| 37 | 
            -
                    instance = builder_instance(object,  | 
| 44 | 
            +
                  def form_for(object, url, options={}, &block)
         | 
| 45 | 
            +
                    instance = builder_instance(object, options)
         | 
| 46 | 
            +
                    # this can erect instance.multipart flag if the block calls instance.file_field
         | 
| 38 47 | 
             
                    html = capture_html(instance, &block)
         | 
| 39 | 
            -
                     | 
| 40 | 
            -
                     | 
| 41 | 
            -
                    settings.delete(:as)
         | 
| 42 | 
            -
                    form_tag(url, settings) { html }
         | 
| 48 | 
            +
                    options = { :multipart => instance.multipart }.update(options.except(:namespace, :as))
         | 
| 49 | 
            +
                    form_tag(url, options) { html }
         | 
| 43 50 | 
             
                  end
         | 
| 44 51 |  | 
| 45 52 | 
             
                  ##
         | 
| @@ -48,7 +55,7 @@ module Padrino | |
| 48 55 | 
             
                  #
         | 
| 49 56 | 
             
                  # @param [Object] object
         | 
| 50 57 | 
             
                  #   The object for which the fields are being built.
         | 
| 51 | 
            -
                  # @param [Hash]  | 
| 58 | 
            +
                  # @param [Hash] options
         | 
| 52 59 | 
             
                  #   The settings associated with these fields. Accepts HTML options.
         | 
| 53 60 | 
             
                  # @param [Proc] block
         | 
| 54 61 | 
             
                  #   The content inside this set of fields.
         | 
| @@ -59,11 +66,11 @@ module Padrino | |
| 59 66 | 
             
                  #   fields_for @user.assignment do |assignment| ... end
         | 
| 60 67 | 
             
                  #   fields_for :assignment do |assigment| ... end
         | 
| 61 68 | 
             
                  #
         | 
| 62 | 
            -
                  def fields_for(object,  | 
| 63 | 
            -
                    instance = builder_instance(object,  | 
| 69 | 
            +
                  def fields_for(object, options={}, &block)
         | 
| 70 | 
            +
                    instance = builder_instance(object, options)
         | 
| 64 71 | 
             
                    fields_html = capture_html(instance, &block)
         | 
| 65 72 | 
             
                    fields_html << instance.hidden_field(:id) if instance.send(:nested_object_id)
         | 
| 66 | 
            -
                     | 
| 73 | 
            +
                    concat_content fields_html
         | 
| 67 74 | 
             
                  end
         | 
| 68 75 |  | 
| 69 76 | 
             
                  ##
         | 
| @@ -82,20 +89,21 @@ module Padrino | |
| 82 89 | 
             
                  #   form_tag '/register', :class => "registration_form" do ... end
         | 
| 83 90 | 
             
                  #
         | 
| 84 91 | 
             
                  def form_tag(url, options={}, &block)
         | 
| 85 | 
            -
                    options =  | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
                                           :protect_from_csrf => is_protected_from_csrf? )
         | 
| 92 | 
            +
                    options = {
         | 
| 93 | 
            +
                      :action => url,
         | 
| 94 | 
            +
                      :protect_from_csrf => is_protected_from_csrf?,
         | 
| 95 | 
            +
                      'accept-charset' => 'UTF-8'
         | 
| 96 | 
            +
                    }.update(options)
         | 
| 91 97 | 
             
                    options[:enctype] = 'multipart/form-data' if options.delete(:multipart)
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                     | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 98 | 
            +
             | 
| 99 | 
            +
                    if (desired_method = options[:method]) =~ /get/i
         | 
| 100 | 
            +
                      options.delete(:protect_from_csrf)
         | 
| 101 | 
            +
                    else
         | 
| 102 | 
            +
                      options[:method] = 'post'
         | 
| 96 103 | 
             
                    end
         | 
| 97 | 
            -
                    inner_form_html  | 
| 98 | 
            -
                     | 
| 104 | 
            +
                    inner_form_html = hidden_form_method_field(desired_method)
         | 
| 105 | 
            +
                    inner_form_html << csrf_token_field if options[:protect_from_csrf]
         | 
| 106 | 
            +
                    concat_content content_tag(:form, inner_form_html << capture_html(&block), options)
         | 
| 99 107 | 
             
                  end
         | 
| 100 108 |  | 
| 101 109 | 
             
                  ##
         | 
| @@ -136,125 +144,9 @@ module Padrino | |
| 136 144 | 
             
                  #
         | 
| 137 145 | 
             
                  def field_set_tag(*args, &block)
         | 
| 138 146 | 
             
                    options = args.extract_options!
         | 
| 139 | 
            -
                    legend_text = args | 
| 147 | 
            +
                    legend_text = args.first
         | 
| 140 148 | 
             
                    legend_html = legend_text.blank? ? ActiveSupport::SafeBuffer.new : content_tag(:legend, legend_text)
         | 
| 141 | 
            -
                     | 
| 142 | 
            -
                    concat_content content_tag(:fieldset, field_set_content, options)
         | 
| 143 | 
            -
                  end
         | 
| 144 | 
            -
             | 
| 145 | 
            -
                  ##
         | 
| 146 | 
            -
                  # Constructs list HTML for the errors for a given symbol.
         | 
| 147 | 
            -
                  #
         | 
| 148 | 
            -
                  # @overload error_messages_for(*objects, options = {})
         | 
| 149 | 
            -
                  #   @param [Array<Object>]  object   Splat of objects to display errors for.
         | 
| 150 | 
            -
                  #   @param [Hash]           options  Error message display options.
         | 
| 151 | 
            -
                  #   @option options [String] :header_tag ("h2")
         | 
| 152 | 
            -
                  #     Used for the header of the error div.
         | 
| 153 | 
            -
                  #   @option options [String] :id ("field-errors")
         | 
| 154 | 
            -
                  #     The id of the error div.
         | 
| 155 | 
            -
                  #   @option options [String] :class ("field-errors")
         | 
| 156 | 
            -
                  #     The class of the error div.
         | 
| 157 | 
            -
                  #   @option options [Array<Object>]  :object
         | 
| 158 | 
            -
                  #     The object (or array of objects) for which to display errors,
         | 
| 159 | 
            -
                  #     if you need to escape the instance variable convention.
         | 
| 160 | 
            -
                  #   @option options [String] :object_name
         | 
| 161 | 
            -
                  #     The object name to use in the header, or any text that you prefer.
         | 
| 162 | 
            -
                  #     If +:object_name+ is not set, the name of the first object will be used.
         | 
| 163 | 
            -
                  #   @option options [String] :header_message ("X errors prohibited this object from being saved")
         | 
| 164 | 
            -
                  #     The message in the header of the error div. Pass +nil+ or an empty string
         | 
| 165 | 
            -
                  #     to avoid the header message altogether.
         | 
| 166 | 
            -
                  #   @option options [String] :message ("There were problems with the following fields:")
         | 
| 167 | 
            -
                  #     The explanation message after the header message and before
         | 
| 168 | 
            -
                  #     the error list.  Pass +nil+ or an empty string to avoid the explanation message
         | 
| 169 | 
            -
                  #     altogether.
         | 
| 170 | 
            -
                  #
         | 
| 171 | 
            -
                  # @return [String] The html section with all errors for the specified +objects+
         | 
| 172 | 
            -
                  #
         | 
| 173 | 
            -
                  # @example
         | 
| 174 | 
            -
                  #   error_messages_for :user
         | 
| 175 | 
            -
                  #
         | 
| 176 | 
            -
                  def error_messages_for(*objects)
         | 
| 177 | 
            -
                    options = objects.extract_options!.symbolize_keys
         | 
| 178 | 
            -
                    objects = objects.map{ |obj| resolve_object(obj) }.compact
         | 
| 179 | 
            -
                    count   = objects.inject(0){ |sum, object| sum + object.errors.count }
         | 
| 180 | 
            -
                    return ''.html_safe if count.zero?
         | 
| 181 | 
            -
             | 
| 182 | 
            -
                    html_options = {}
         | 
| 183 | 
            -
                    [:id, :class, :style].each do |key|
         | 
| 184 | 
            -
                      if options.include?(key)
         | 
| 185 | 
            -
                        value = options[key]
         | 
| 186 | 
            -
                        html_options[key] = value unless value.blank?
         | 
| 187 | 
            -
                      else
         | 
| 188 | 
            -
                        html_options[key] = 'field-errors' unless key == :style
         | 
| 189 | 
            -
                      end
         | 
| 190 | 
            -
                    end
         | 
| 191 | 
            -
             | 
| 192 | 
            -
                    I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
         | 
| 193 | 
            -
                      object_name = options[:object_name] || objects.first.class.to_s.underscore.gsub(/\//, ' ')
         | 
| 194 | 
            -
             | 
| 195 | 
            -
                      header_message = if options.include?(:header_message)
         | 
| 196 | 
            -
                        options[:header_message]
         | 
| 197 | 
            -
                      else
         | 
| 198 | 
            -
                        model_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
         | 
| 199 | 
            -
                        locale.t :header, :count => count, :model => model_name
         | 
| 200 | 
            -
                      end
         | 
| 201 | 
            -
             | 
| 202 | 
            -
                      body_message = options[:message] || locale.t(:body)
         | 
| 203 | 
            -
             | 
| 204 | 
            -
                      error_messages = objects.inject(''.html_safe) do |text, object|
         | 
| 205 | 
            -
                        object.errors.each do |field, message|
         | 
| 206 | 
            -
                          field_name = I18n.t(field, :default => field.to_s.humanize, :scope => [:models, object_name, :attributes])
         | 
| 207 | 
            -
                          text << content_tag(:li, "#{field_name} #{message}")
         | 
| 208 | 
            -
                        end
         | 
| 209 | 
            -
                        text
         | 
| 210 | 
            -
                      end
         | 
| 211 | 
            -
             | 
| 212 | 
            -
                      contents = ActiveSupport::SafeBuffer.new
         | 
| 213 | 
            -
                      contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
         | 
| 214 | 
            -
                      contents << content_tag(:p, body_message) unless body_message.blank?
         | 
| 215 | 
            -
                      contents << content_tag(:ul, error_messages)
         | 
| 216 | 
            -
                      content_tag(:div, contents, html_options)
         | 
| 217 | 
            -
                    end
         | 
| 218 | 
            -
                  end
         | 
| 219 | 
            -
             | 
| 220 | 
            -
                  ##
         | 
| 221 | 
            -
                  # Returns a string containing the error message attached to the
         | 
| 222 | 
            -
                  # +method+ on the +object+ if one exists.
         | 
| 223 | 
            -
                  #
         | 
| 224 | 
            -
                  # @param [Object] object
         | 
| 225 | 
            -
                  #   The object to display the error for.
         | 
| 226 | 
            -
                  # @param [Symbol] field
         | 
| 227 | 
            -
                  #   The field on the +object+ to display the error for.
         | 
| 228 | 
            -
                  # @param [Hash] options
         | 
| 229 | 
            -
                  #   The options to control the error display.
         | 
| 230 | 
            -
                  # @option options [String] :tag ("span")
         | 
| 231 | 
            -
                  #   The tag that encloses the error.
         | 
| 232 | 
            -
                  # @option options [String] :prepend ("")
         | 
| 233 | 
            -
                  #   The text to prepend before the field error.
         | 
| 234 | 
            -
                  # @option options [String] :append ("")
         | 
| 235 | 
            -
                  #   The text to append after the field error.
         | 
| 236 | 
            -
                  #
         | 
| 237 | 
            -
                  # @example
         | 
| 238 | 
            -
                  #   # => <span class="error">can't be blank</div>
         | 
| 239 | 
            -
                  #   error_message_on :post, :title
         | 
| 240 | 
            -
                  #   error_message_on @post, :title
         | 
| 241 | 
            -
                  #
         | 
| 242 | 
            -
                  #   # => <div class="custom" style="border:1px solid red">can't be blank</div>
         | 
| 243 | 
            -
                  #   error_message_on :post, :title, :tag => :id, :class => :custom, :style => "border:1px solid red"
         | 
| 244 | 
            -
                  #
         | 
| 245 | 
            -
                  #   # => <div class="error">This title can't be blank (or it won't work)</div>
         | 
| 246 | 
            -
                  #   error_message_on :post, :title, :prepend => "This title", :append => "(or it won't work)"
         | 
| 247 | 
            -
                  #
         | 
| 248 | 
            -
                  # @return [String] The html display of an error for a particular +object+ and +field+.
         | 
| 249 | 
            -
                  #
         | 
| 250 | 
            -
                  # @api public
         | 
| 251 | 
            -
                  def error_message_on(object, field, options={})
         | 
| 252 | 
            -
                    error = Array(resolve_object(object).errors[field]).first
         | 
| 253 | 
            -
                    return ''.html_safe unless error
         | 
| 254 | 
            -
                    options = options.reverse_merge(:tag => :span, :class => :error)
         | 
| 255 | 
            -
                    tag   = options.delete(:tag)
         | 
| 256 | 
            -
                    error = [options.delete(:prepend), error, options.delete(:append)].compact.join(" ")
         | 
| 257 | 
            -
                    content_tag(tag, error, options)
         | 
| 149 | 
            +
                    concat_content content_tag(:fieldset, legend_html << capture_html(&block), options)
         | 
| 258 150 | 
             
                  end
         | 
| 259 151 |  | 
| 260 152 | 
             
                  ##
         | 
| @@ -276,14 +168,12 @@ module Padrino | |
| 276 168 | 
             
                  #   label_tag :username, :class => 'long-label' do ... end
         | 
| 277 169 | 
             
                  #
         | 
| 278 170 | 
             
                  def label_tag(name, options={}, &block)
         | 
| 279 | 
            -
                    options =  | 
| 280 | 
            -
                    caption_text =  | 
| 281 | 
            -
                    caption_text. | 
| 282 | 
            -
                    caption_text.safe_concat "<span class='required'>*</span> " if options.delete(:required)
         | 
| 171 | 
            +
                    options = { :caption => "#{name.to_s.humanize}: ", :for => name }.update(options)
         | 
| 172 | 
            +
                    caption_text = ActiveSupport::SafeBuffer.new << options.delete(:caption)
         | 
| 173 | 
            +
                    caption_text << "<span class='required'>*</span> ".html_safe if options.delete(:required)
         | 
| 283 174 |  | 
| 284 175 | 
             
                    if block_given?
         | 
| 285 | 
            -
                       | 
| 286 | 
            -
                      concat_content(content_tag(:label, label_content, options))
         | 
| 176 | 
            +
                      concat_content content_tag(:label, caption_text << capture_html(&block), options)
         | 
| 287 177 | 
             
                    else
         | 
| 288 178 | 
             
                      content_tag(:label, caption_text, options)
         | 
| 289 179 | 
             
                    end
         | 
| @@ -347,7 +237,7 @@ module Padrino | |
| 347 237 | 
             
                  #   # => <input name="username" placeholder="Your Username" type="text" />
         | 
| 348 238 | 
             
                  #
         | 
| 349 239 | 
             
                  def text_field_tag(name, options={})
         | 
| 350 | 
            -
                    input_tag(:text,  | 
| 240 | 
            +
                    input_tag(:text, { :name => name }.update(options))
         | 
| 351 241 | 
             
                  end
         | 
| 352 242 |  | 
| 353 243 | 
             
                  ##
         | 
| @@ -411,7 +301,7 @@ module Padrino | |
| 411 301 | 
             
                  #   # => <input name="age" min="18" max="120" step="1" type="number" />
         | 
| 412 302 | 
             
                  #
         | 
| 413 303 | 
             
                  def number_field_tag(name, options={})
         | 
| 414 | 
            -
                    input_tag(:number,  | 
| 304 | 
            +
                    input_tag(:number, { :name => name }.update(options))
         | 
| 415 305 | 
             
                  end
         | 
| 416 306 |  | 
| 417 307 | 
             
                  ##
         | 
| @@ -432,7 +322,7 @@ module Padrino | |
| 432 322 | 
             
                  #  # => <input name="home_phone" tabindex="3" type="tel" />
         | 
| 433 323 | 
             
                  #
         | 
| 434 324 | 
             
                  def telephone_field_tag(name, options={})
         | 
| 435 | 
            -
                    input_tag(:tel,  | 
| 325 | 
            +
                    input_tag(:tel, { :name => name }.update(options))
         | 
| 436 326 | 
             
                  end
         | 
| 437 327 | 
             
                  alias_method :phone_field_tag, :telephone_field_tag
         | 
| 438 328 |  | 
| @@ -449,7 +339,7 @@ module Padrino | |
| 449 339 | 
             
                  #   # => <input name="email" value="padrinorb@gmail.com" readonly type="email" />
         | 
| 450 340 | 
             
                  #
         | 
| 451 341 | 
             
                  def email_field_tag(name, options={})
         | 
| 452 | 
            -
                    input_tag(:email,  | 
| 342 | 
            +
                    input_tag(:email, { :name => name }.update(options))
         | 
| 453 343 | 
             
                  end
         | 
| 454 344 |  | 
| 455 345 | 
             
                  ##
         | 
| @@ -471,7 +361,7 @@ module Padrino | |
| 471 361 | 
             
                  #  # => <input name="search" autofocus type="search" />
         | 
| 472 362 | 
             
                  #
         | 
| 473 363 | 
             
                  def search_field_tag(name, options={})
         | 
| 474 | 
            -
                    input_tag(:search,  | 
| 364 | 
            +
                    input_tag(:search, { :name => name }.update(options))
         | 
| 475 365 | 
             
                  end
         | 
| 476 366 |  | 
| 477 367 | 
             
                  ##
         | 
| @@ -487,7 +377,7 @@ module Padrino | |
| 487 377 | 
             
                  #  <input name="home_page" class="string url", type="url" />
         | 
| 488 378 | 
             
                  #
         | 
| 489 379 | 
             
                  def url_field_tag(name, options={})
         | 
| 490 | 
            -
                    input_tag(:url,  | 
| 380 | 
            +
                    input_tag(:url, { :name => name }.update(options))
         | 
| 491 381 | 
             
                  end
         | 
| 492 382 |  | 
| 493 383 | 
             
                  ##
         | 
| @@ -497,7 +387,7 @@ module Padrino | |
| 497 387 | 
             
                  #   hidden_field_tag :session_key, :value => "__secret__"
         | 
| 498 388 | 
             
                  #
         | 
| 499 389 | 
             
                  def hidden_field_tag(name, options={})
         | 
| 500 | 
            -
                    input_tag(:hidden,  | 
| 390 | 
            +
                    input_tag(:hidden, { :name => name }.update(options))
         | 
| 501 391 | 
             
                  end
         | 
| 502 392 |  | 
| 503 393 | 
             
                  ##
         | 
| @@ -507,8 +397,9 @@ module Padrino | |
| 507 397 | 
             
                  #   text_area_tag :username, :class => 'long', :value => "Demo?"
         | 
| 508 398 | 
             
                  #
         | 
| 509 399 | 
             
                  def text_area_tag(name, options={})
         | 
| 510 | 
            -
                     | 
| 511 | 
            -
                     | 
| 400 | 
            +
                    inner_html = options.delete(:value).to_s
         | 
| 401 | 
            +
                    options = { :name => name, :rows => "", :cols => "" }.update(options)
         | 
| 402 | 
            +
                    content_tag(:textarea, inner_html, options)
         | 
| 512 403 | 
             
                  end
         | 
| 513 404 |  | 
| 514 405 | 
             
                  ##
         | 
| @@ -519,7 +410,7 @@ module Padrino | |
| 519 410 | 
             
                  #
         | 
| 520 411 | 
             
                  # @api public
         | 
| 521 412 | 
             
                  def password_field_tag(name, options={})
         | 
| 522 | 
            -
                    input_tag(:password,  | 
| 413 | 
            +
                    input_tag(:password, { :name => name }.update(options))
         | 
| 523 414 | 
             
                  end
         | 
| 524 415 |  | 
| 525 416 | 
             
                  ##
         | 
| @@ -529,7 +420,7 @@ module Padrino | |
| 529 420 | 
             
                  #   check_box_tag :remember_me, :value => 'Yes'
         | 
| 530 421 | 
             
                  #
         | 
| 531 422 | 
             
                  def check_box_tag(name, options={})
         | 
| 532 | 
            -
                    input_tag(:checkbox,  | 
| 423 | 
            +
                    input_tag(:checkbox, { :name => name, :value => '1' }.update(options))
         | 
| 533 424 | 
             
                  end
         | 
| 534 425 |  | 
| 535 426 | 
             
                  ##
         | 
| @@ -539,7 +430,7 @@ module Padrino | |
| 539 430 | 
             
                  #   radio_button_tag :remember_me, :value => 'true'
         | 
| 540 431 | 
             
                  #
         | 
| 541 432 | 
             
                  def radio_button_tag(name, options={})
         | 
| 542 | 
            -
                    input_tag(:radio,  | 
| 433 | 
            +
                    input_tag(:radio, { :name => name }.update(options))
         | 
| 543 434 | 
             
                  end
         | 
| 544 435 |  | 
| 545 436 | 
             
                  ##
         | 
| @@ -551,7 +442,7 @@ module Padrino | |
| 551 442 | 
             
                  # @api public
         | 
| 552 443 | 
             
                  def file_field_tag(name, options={})
         | 
| 553 444 | 
             
                    name = "#{name}[]" if options[:multiple]
         | 
| 554 | 
            -
                    input_tag(:file,  | 
| 445 | 
            +
                    input_tag(:file, { :name => name }.update(options))
         | 
| 555 446 | 
             
                  end
         | 
| 556 447 |  | 
| 557 448 | 
             
                  ##
         | 
| @@ -595,12 +486,9 @@ module Padrino | |
| 595 486 | 
             
                  # @return [String] The HTML input field based on the +options+ specified.
         | 
| 596 487 | 
             
                  #
         | 
| 597 488 | 
             
                  def select_tag(name, options={})
         | 
| 598 | 
            -
                    options =  | 
| 489 | 
            +
                    options = { :name => name }.merge(options)
         | 
| 599 490 | 
             
                    options[:name] = "#{options[:name]}[]" if options[:multiple]
         | 
| 600 | 
            -
                     | 
| 601 | 
            -
                    options[:options] = options_from_collection(collection, fields) if collection
         | 
| 602 | 
            -
                    options_tags = extract_option_tags!(options)
         | 
| 603 | 
            -
                    content_tag(:select, options_tags, options)
         | 
| 491 | 
            +
                    content_tag(:select, extract_option_tags!(options), options)
         | 
| 604 492 | 
             
                  end
         | 
| 605 493 |  | 
| 606 494 | 
             
                  ##
         | 
| @@ -617,7 +505,7 @@ module Padrino | |
| 617 505 | 
             
                  #   button_tag "Cancel", :class => 'clear'
         | 
| 618 506 | 
             
                  #
         | 
| 619 507 | 
             
                  def button_tag(caption, options = {})
         | 
| 620 | 
            -
                    input_tag(:button,  | 
| 508 | 
            +
                    input_tag(:button, { :value => caption }.update(options))
         | 
| 621 509 | 
             
                  end
         | 
| 622 510 |  | 
| 623 511 | 
             
                  ##
         | 
| @@ -637,7 +525,7 @@ module Padrino | |
| 637 525 | 
             
                  def submit_tag(*args)
         | 
| 638 526 | 
             
                    options = args.extract_options!
         | 
| 639 527 | 
             
                    caption = args.length >= 1 ? args.first : "Submit"
         | 
| 640 | 
            -
                    input_tag(:submit,  | 
| 528 | 
            +
                    input_tag(:submit, { :value => caption }.merge(options))
         | 
| 641 529 | 
             
                  end
         | 
| 642 530 |  | 
| 643 531 | 
             
                  ##
         | 
| @@ -654,38 +542,7 @@ module Padrino | |
| 654 542 | 
             
                  #   image_submit_tag 'form/submit.png'
         | 
| 655 543 | 
             
                  #
         | 
| 656 544 | 
             
                  def image_submit_tag(source, options={})
         | 
| 657 | 
            -
                    input_tag(:image,  | 
| 658 | 
            -
                  end
         | 
| 659 | 
            -
             | 
| 660 | 
            -
                  ##
         | 
| 661 | 
            -
                  # Constructs a hidden field containing a CSRF token.
         | 
| 662 | 
            -
                  #
         | 
| 663 | 
            -
                  # @param [String] token
         | 
| 664 | 
            -
                  #   The token to use. Will be read from the session by default.
         | 
| 665 | 
            -
                  #
         | 
| 666 | 
            -
                  # @return [String] The hidden field with CSRF token as value.
         | 
| 667 | 
            -
                  #
         | 
| 668 | 
            -
                  # @example
         | 
| 669 | 
            -
                  #   csrf_token_field
         | 
| 670 | 
            -
                  #
         | 
| 671 | 
            -
                  def csrf_token_field(token = nil)
         | 
| 672 | 
            -
                    hidden_field_tag csrf_param, :value => csrf_token
         | 
| 673 | 
            -
                  end
         | 
| 674 | 
            -
             | 
| 675 | 
            -
                  ##
         | 
| 676 | 
            -
                  # Constructs meta tags `csrf-param` and `csrf-token` with the name of the
         | 
| 677 | 
            -
                  # cross-site request forgery protection parameter and token, respectively.
         | 
| 678 | 
            -
                  #
         | 
| 679 | 
            -
                  # @return [String] The meta tags with the CSRF token and the param your app expects it in.
         | 
| 680 | 
            -
                  #
         | 
| 681 | 
            -
                  # @example
         | 
| 682 | 
            -
                  #   csrf_meta_tags
         | 
| 683 | 
            -
                  #
         | 
| 684 | 
            -
                  def csrf_meta_tags
         | 
| 685 | 
            -
                    if is_protected_from_csrf?
         | 
| 686 | 
            -
                      meta_tag(csrf_param, :name => 'csrf-param') <<
         | 
| 687 | 
            -
                      meta_tag(csrf_token, :name => 'csrf-token')
         | 
| 688 | 
            -
                    end
         | 
| 545 | 
            +
                    input_tag(:image, { :src => image_path(source) }.update(options))
         | 
| 689 546 | 
             
                  end
         | 
| 690 547 |  | 
| 691 548 | 
             
                  ##
         | 
| @@ -721,16 +578,10 @@ module Padrino | |
| 721 578 | 
             
                  #
         | 
| 722 579 | 
             
                  def button_to(*args, &block)
         | 
| 723 580 | 
             
                    options   = args.extract_options!.dup
         | 
| 724 | 
            -
                    name, url = args | 
| 581 | 
            +
                    name, url = *args
         | 
| 725 582 | 
             
                    options['data-remote'] = 'true' if options.delete(:remote)
         | 
| 726 | 
            -
                     | 
| 727 | 
            -
                     | 
| 728 | 
            -
                      form_tag(url || name, options, &block)
         | 
| 729 | 
            -
                    else
         | 
| 730 | 
            -
                      form_tag(url, options) do
         | 
| 731 | 
            -
                        submit_tag(name, submit_options)
         | 
| 732 | 
            -
                      end
         | 
| 733 | 
            -
                    end
         | 
| 583 | 
            +
                    block ||= proc { submit_tag(name, options.delete(:submit_options) || {}) }
         | 
| 584 | 
            +
                    form_tag(url || name, options, &block)
         | 
| 734 585 | 
             
                  end
         | 
| 735 586 |  | 
| 736 587 | 
             
                  ##
         | 
| @@ -753,158 +604,26 @@ module Padrino | |
| 753 604 | 
             
                  # @return [String] The html range field
         | 
| 754 605 | 
             
                  #
         | 
| 755 606 | 
             
                  def range_field_tag(name, options = {})
         | 
| 756 | 
            -
                    options =  | 
| 607 | 
            +
                    options = { :name => name }.update(options)
         | 
| 757 608 | 
             
                    if range = options.delete(:range)
         | 
| 758 609 | 
             
                      options[:min], options[:max] = range.min, range.max
         | 
| 759 610 | 
             
                    end
         | 
| 760 611 | 
             
                    input_tag(:range, options)
         | 
| 761 612 | 
             
                  end
         | 
| 762 613 |  | 
| 763 | 
            -
                  protected
         | 
| 764 | 
            -
             | 
| 765 | 
            -
                  ##
         | 
| 766 | 
            -
                  # Returns an array of option items for a select field based on the given collection.
         | 
| 767 | 
            -
                  #
         | 
| 768 | 
            -
                  # @param [Array] fields
         | 
| 769 | 
            -
                  #   fields is an array containing the fields to display from each item in the collection.
         | 
| 770 | 
            -
                  #
         | 
| 771 | 
            -
                  def options_from_collection(collection, fields)
         | 
| 772 | 
            -
                    collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
         | 
| 773 | 
            -
                  end
         | 
| 774 | 
            -
             | 
| 775 | 
            -
                  ##
         | 
| 776 | 
            -
                  # Returns the options tags for a select based on the given option items.
         | 
| 777 | 
            -
                  #
         | 
| 778 | 
            -
                  def options_for_select(option_items, state = {})
         | 
| 779 | 
            -
                    return [] if option_items.blank?
         | 
| 780 | 
            -
                    option_items.map do |caption, value, attributes|
         | 
| 781 | 
            -
                      html_attributes = { :value => value || caption  }.merge(attributes||{})
         | 
| 782 | 
            -
                      html_attributes[:selected] ||= option_is_selected?(value, caption, state[:selected])
         | 
| 783 | 
            -
                      html_attributes[:disabled] ||= option_is_selected?(value, caption, state[:disabled])
         | 
| 784 | 
            -
                      content_tag(:option, caption, html_attributes)
         | 
| 785 | 
            -
                    end
         | 
| 786 | 
            -
                  end
         | 
| 787 | 
            -
             | 
| 788 | 
            -
                  ##
         | 
| 789 | 
            -
                  # Returns the optgroups with options tags for a select based on the given :grouped_options items.
         | 
| 790 | 
            -
                  #
         | 
| 791 | 
            -
                  def grouped_options_for_select(collection, state = {})
         | 
| 792 | 
            -
                    collection.map do |item|
         | 
| 793 | 
            -
                      caption = item.shift
         | 
| 794 | 
            -
                      attributes = item.last.kind_of?(Hash) ? item.pop : {}
         | 
| 795 | 
            -
                      value = item.flatten(1)
         | 
| 796 | 
            -
                      attributes = value.pop if value.last.kind_of?(Hash)
         | 
| 797 | 
            -
                      html_attributes = { :label => caption }.merge(attributes||{})
         | 
| 798 | 
            -
                      content_tag(:optgroup, options_for_select(value, state), html_attributes)
         | 
| 799 | 
            -
                    end
         | 
| 800 | 
            -
                  end
         | 
| 801 | 
            -
             | 
| 802 | 
            -
                  ##
         | 
| 803 | 
            -
                  # Returns the blank option serving as a prompt if passed.
         | 
| 804 | 
            -
                  #
         | 
| 805 | 
            -
                  def blank_option(prompt)
         | 
| 806 | 
            -
                    case prompt
         | 
| 807 | 
            -
                    when nil, false
         | 
| 808 | 
            -
                      nil
         | 
| 809 | 
            -
                    when String
         | 
| 810 | 
            -
                      content_tag(:option, prompt,       :value => '')
         | 
| 811 | 
            -
                    when Array
         | 
| 812 | 
            -
                      content_tag(:option, prompt.first, :value => prompt.last)
         | 
| 813 | 
            -
                    else
         | 
| 814 | 
            -
                      content_tag(:option, '',           :value => '')
         | 
| 815 | 
            -
                    end
         | 
| 816 | 
            -
                  end
         | 
| 817 | 
            -
             | 
| 818 | 
            -
                  ##
         | 
| 819 | 
            -
                  # Returns whether the application is being protected from CSRF. Defaults to true.
         | 
| 820 | 
            -
                  #
         | 
| 821 | 
            -
                  def is_protected_from_csrf?
         | 
| 822 | 
            -
                    defined?(settings) ? settings.protect_from_csrf : true
         | 
| 823 | 
            -
                  end
         | 
| 824 | 
            -
             | 
| 825 | 
            -
                  ##
         | 
| 826 | 
            -
                  # Returns the current CSRF token (based on the session). If it doesn't exist,
         | 
| 827 | 
            -
                  # it will create one and assign it to the session's `csrf` key.
         | 
| 828 | 
            -
                  #
         | 
| 829 | 
            -
                  def csrf_token
         | 
| 830 | 
            -
                    session[:csrf] ||= SecureRandom.hex(32) if defined?(session)
         | 
| 831 | 
            -
                  end
         | 
| 832 | 
            -
             | 
| 833 | 
            -
                  ##
         | 
| 834 | 
            -
                  # Returns the param/field name in which your CSRF token should be expected by your
         | 
| 835 | 
            -
                  # controllers. Defaults to `authenticity_token`.
         | 
| 836 | 
            -
                  #
         | 
| 837 | 
            -
                  # Set this in your application with `set :csrf_param, :something_else`.
         | 
| 838 | 
            -
                  #
         | 
| 839 | 
            -
                  def csrf_param
         | 
| 840 | 
            -
                    defined?(settings) && settings.respond_to?(:csrf_param) ?
         | 
| 841 | 
            -
                      settings.csrf_param : :authenticity_token
         | 
| 842 | 
            -
                  end
         | 
| 843 | 
            -
             | 
| 844 614 | 
             
                  private
         | 
| 845 615 |  | 
| 846 | 
            -
                  ##
         | 
| 847 | 
            -
                  # Returns the FormBuilder class to use based on all available setting sources
         | 
| 848 | 
            -
                  # If explicitly defined, returns that, otherwise returns defaults.
         | 
| 849 | 
            -
                  #
         | 
| 850 | 
            -
                  # @example
         | 
| 851 | 
            -
                  #   configured_form_builder_class(nil) => StandardFormBuilder
         | 
| 852 | 
            -
                  #
         | 
| 853 | 
            -
                  def configured_form_builder_class(explicit_builder=nil)
         | 
| 854 | 
            -
                    default_builder    = self.respond_to?(:settings) && self.settings.default_builder
         | 
| 855 | 
            -
                    configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
         | 
| 856 | 
            -
                    configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
         | 
| 857 | 
            -
                    configured_builder
         | 
| 858 | 
            -
                  end
         | 
| 859 | 
            -
             | 
| 860 616 | 
             
                  ##
         | 
| 861 617 | 
             
                  # Returns an initialized builder instance for the given object and settings.
         | 
| 862 618 | 
             
                  #
         | 
| 863 619 | 
             
                  # @example
         | 
| 864 620 | 
             
                  #   builder_instance(@account, :nested => { ... }) => <FormBuilder>
         | 
| 865 621 | 
             
                  #
         | 
| 866 | 
            -
                  def builder_instance(object,  | 
| 867 | 
            -
             | 
| 868 | 
            -
             | 
| 869 | 
            -
             | 
| 870 | 
            -
             | 
| 871 | 
            -
                  ##
         | 
| 872 | 
            -
                  # Returns whether the option should be selected or not.
         | 
| 873 | 
            -
                  #
         | 
| 874 | 
            -
                  # @example
         | 
| 875 | 
            -
                  #   option_is_selected?("red", "Red", ["red", "blue"])   => true
         | 
| 876 | 
            -
                  #   option_is_selected?("red", "Red", ["green", "blue"]) => false
         | 
| 877 | 
            -
                  #
         | 
| 878 | 
            -
                  def option_is_selected?(value, caption, selected_values)
         | 
| 879 | 
            -
                    Array(selected_values).any? do |selected|
         | 
| 880 | 
            -
                      [value.to_s, caption.to_s].include?(selected.to_s)
         | 
| 881 | 
            -
                    end
         | 
| 882 | 
            -
                  end
         | 
| 883 | 
            -
             | 
| 884 | 
            -
                  def extract_option_state!(options)
         | 
| 885 | 
            -
                    {
         | 
| 886 | 
            -
                      :selected => Array(options.delete(:selected))|Array(options.delete(:selected_options)),
         | 
| 887 | 
            -
                      :disabled => Array(options.delete(:disabled_options))
         | 
| 888 | 
            -
                    }
         | 
| 889 | 
            -
                  end
         | 
| 890 | 
            -
             | 
| 891 | 
            -
                  def extract_option_tags!(options)
         | 
| 892 | 
            -
                    state = extract_option_state!(options)
         | 
| 893 | 
            -
                    option_tags = case
         | 
| 894 | 
            -
                    when options[:options]
         | 
| 895 | 
            -
                      options_for_select(options.delete(:options), state)
         | 
| 896 | 
            -
                    when options[:grouped_options]
         | 
| 897 | 
            -
                      grouped_options_for_select(options.delete(:grouped_options), state)
         | 
| 898 | 
            -
                    else
         | 
| 899 | 
            -
                      []
         | 
| 900 | 
            -
                    end
         | 
| 901 | 
            -
                    prompt = options.delete(:include_blank)
         | 
| 902 | 
            -
                    option_tags.unshift(blank_option(prompt)) if prompt
         | 
| 903 | 
            -
                    option_tags
         | 
| 904 | 
            -
                  end
         | 
| 905 | 
            -
             | 
| 906 | 
            -
                  def resolve_object(object)
         | 
| 907 | 
            -
                    object.is_a?(Symbol) ? instance_variable_get("@#{object}") : object
         | 
| 622 | 
            +
                  def builder_instance(object, options={})
         | 
| 623 | 
            +
                    default_builder = respond_to?(:settings) && settings.default_builder || 'StandardFormBuilder'
         | 
| 624 | 
            +
                    builder_class = options.delete(:builder) || default_builder
         | 
| 625 | 
            +
                    builder_class = "Padrino::Helpers::FormBuilder::#{builder_class}".constantize if builder_class.is_a?(String)
         | 
| 626 | 
            +
                    builder_class.new(self, object, options)
         | 
| 908 627 | 
             
                  end
         | 
| 909 628 | 
             
                end
         | 
| 910 629 | 
             
              end
         |