def extract_options!(options, html_options: nil)
      options.symbolize_keys!
      html_options.symbolize_keys! if html_options

      # effective_bootstrap specific options
      layout = options.delete(:layout) # Symbol
      wrapper = options.delete(:wrapper) # Hash
      input_group = { append: options.delete(:append), prepend: options.delete(:prepend), input_group: options.delete(:input_group) }.compact

      feedback = options.delete(:feedback) # Hash
      label = options.delete(:label) # String or Hash
      hint = options.delete(:hint) # String or Hash

      input_html = options.delete(:input_html) || {} # Hash
      input_js = options.delete(:input_js) || {} # Hash

      # Every other option goes to input
      @options = input = (html_options || options)

      # Merge all the default objects, and intialize everything
      wrapper = merge_defaults!(wrapper, wrapper_options)
      input_group = merge_defaults!(input_group, input_group_options)
      feedback = merge_defaults!(feedback, feedback_options)

      label = merge_defaults!(label, label_options)
      hint = merge_defaults!(hint, hint_options)

      merge_defaults!(input.merge!(input_html), input_html_options)
      merge_defaults!(input_js, input_js_options)

      if input_js.present?
        merge_defaults!(input_js, input_js_options_method_name)
        input['data-input-js-options'] = JSON.generate(input_js)
      end

      { layout: layout, wrapper: wrapper, input_group: input_group, label: label, hint: hint, input: input, feedback: feedback }
    end
def extract_options!(options, html_options: nil)
      options.symbolize_keys!
      html_options.symbolize_keys! if html_options

      # effective_bootstrap specific options
      layout = options.delete(:layout) # Symbol
      wrapper = options.delete(:wrapper) # Hash
      input_group = { append: options.delete(:append), prepend: options.delete(:prepend), input_group: options.delete(:input_group) }.compact

      feedback = options.delete(:feedback) # Hash
      label = options.delete(:label) # String or Hash
      hint = options.delete(:hint) # String or Hash

      input_html = options.delete(:input_html) || {} # Hash
      input_js = options.delete(:input_js) || {} # Hash

      # Every other option goes to input
      @options = input = (html_options || options)

      # Merge all the default objects, and intialize everything
      wrapper = merge_defaults!(wrapper, wrapper_options)
      input_group = merge_defaults!(input_group, input_group_options)
      feedback = merge_defaults!(feedback, feedback_options)

      label = merge_defaults!(label, label_options)
      hint = merge_defaults!(hint, hint_options)

      merge_defaults!(input.merge!(input_html), input_html_options)
      merge_defaults!(input_js, input_js_options)

      if input_js.present?
        merge_defaults!(input_js, input_js_options_method_name)
        input['data-input-js-options'] = JSON.generate(input_js)
      end

      { layout: layout, wrapper: wrapper, input_group: input_group, label: label, hint: hint, input: input, feedback: feedback }
    end
Here we split them into { wrapper: {}, label: {}, hint: {}, input: {} }
 And make sure to keep any additional options on the input: {}