diff --git a/lib/simple_form.rb b/lib/simple_form.rb index a241bf27..26eed85a 100644 --- a/lib/simple_form.rb +++ b/lib/simple_form.rb @@ -24,6 +24,18 @@ module SimpleForm SimpleForm::Components.eager_load! end + CUSTOM_INPUT_DEPRECATION_WARN = <<-WARN +%{name} method now accepts a `wrapper_options` argument. The method definition without the argument is deprecated and will be removed in the next Simple Form version. Change your code from: + + def %{name} + +to + + def %{name}(wrapper_options) + +See https://github.com/plataformatec/simple_form/pull/997 for more information. + WARN + ## CONFIGURATION OPTIONS # Method used to tidy up errors. @@ -189,7 +201,7 @@ module SimpleForm end # Builds a new wrapper using SimpleForm::Wrappers::Builder. - def self.build(options={}) + def self.build(options = {}) options[:tag] = :div if options[:tag].nil? builder = SimpleForm::Wrappers::Builder.new(options) yield builder diff --git a/lib/simple_form/action_view_extensions/form_helper.rb b/lib/simple_form/action_view_extensions/form_helper.rb index 1a2d3017..e5bf66b0 100644 --- a/lib/simple_form/action_view_extensions/form_helper.rb +++ b/lib/simple_form/action_view_extensions/form_helper.rb @@ -10,7 +10,7 @@ module SimpleForm # module FormHelper - def simple_form_for(record, options={}, &block) + def simple_form_for(record, options = {}, &block) options[:builder] ||= SimpleForm::FormBuilder options[:html] ||= {} unless options[:html].key?(:novalidate) diff --git a/lib/simple_form/components/errors.rb b/lib/simple_form/components/errors.rb index aad48335..b4bacf85 100644 --- a/lib/simple_form/components/errors.rb +++ b/lib/simple_form/components/errors.rb @@ -1,7 +1,7 @@ module SimpleForm module Components module Errors - def error + def error(wrapper_options = nil) error_text if has_errors? end diff --git a/lib/simple_form/components/hints.rb b/lib/simple_form/components/hints.rb index f9890d5b..9323101d 100644 --- a/lib/simple_form/components/hints.rb +++ b/lib/simple_form/components/hints.rb @@ -2,7 +2,7 @@ module SimpleForm module Components # Needs to be enabled in order to do automatic lookups. module Hints - def hint + def hint(wrapper_options = nil) @hint ||= begin hint = options[:hint] diff --git a/lib/simple_form/components/html5.rb b/lib/simple_form/components/html5.rb index e3bec5bd..9d4fe515 100644 --- a/lib/simple_form/components/html5.rb +++ b/lib/simple_form/components/html5.rb @@ -5,7 +5,7 @@ module SimpleForm @html5 = false end - def html5 + def html5(wrapper_options = nil) @html5 = true if has_required? input_html_options[:required] = true diff --git a/lib/simple_form/components/label_input.rb b/lib/simple_form/components/label_input.rb index f2be3ac3..080fdd96 100644 --- a/lib/simple_form/components/label_input.rb +++ b/lib/simple_form/components/label_input.rb @@ -7,8 +7,26 @@ module SimpleForm include SimpleForm::Components::Labels end - def label_input - options[:label] == false ? input : (label + input) + def label_input(wrapper_options = nil) + if options[:label] == false + deprecated_component(:input, wrapper_options) + else + deprecated_component(:label, wrapper_options) + deprecated_component(:input, wrapper_options) + end + end + + private + + def deprecated_component(namespace, wrapper_options) + method = method(namespace) + + if method.arity == 0 + ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: namespace }) + + method.call + else + method.call(wrapper_options) + end end end end diff --git a/lib/simple_form/components/labels.rb b/lib/simple_form/components/labels.rb index ae33f5d2..5943a37c 100644 --- a/lib/simple_form/components/labels.rb +++ b/lib/simple_form/components/labels.rb @@ -21,11 +21,13 @@ module SimpleForm end end - def label + def label(wrapper_options = nil) + label_options = merge_wrapper_options(label_html_options, wrapper_options) + if generate_label_for_attribute? - @builder.label(label_target, label_text, label_html_options) + @builder.label(label_target, label_text, label_options) else - template.label_tag(nil, label_text, label_html_options) + template.label_tag(nil, label_text, label_options) end end @@ -46,6 +48,7 @@ module SimpleForm if options.key?(:input_html) && options[:input_html].key?(:id) label_options[:for] = options[:input_html][:id] end + label_options end diff --git a/lib/simple_form/components/maxlength.rb b/lib/simple_form/components/maxlength.rb index 8ad42646..ebb265e7 100644 --- a/lib/simple_form/components/maxlength.rb +++ b/lib/simple_form/components/maxlength.rb @@ -2,7 +2,7 @@ module SimpleForm module Components # Needs to be enabled in order to do automatic lookups. module Maxlength - def maxlength + def maxlength(wrapper_options = nil) input_html_options[:maxlength] ||= maximum_length_from_validation || limit nil end diff --git a/lib/simple_form/components/min_max.rb b/lib/simple_form/components/min_max.rb index 234845c2..95c24ac8 100644 --- a/lib/simple_form/components/min_max.rb +++ b/lib/simple_form/components/min_max.rb @@ -1,7 +1,7 @@ module SimpleForm module Components module MinMax - def min_max + def min_max(wrapper_options = nil) if numeric_validator = find_numericality_validator validator_options = numeric_validator.options input_html_options[:min] ||= minimum_value(validator_options) diff --git a/lib/simple_form/components/pattern.rb b/lib/simple_form/components/pattern.rb index 889a7333..82a21a5d 100644 --- a/lib/simple_form/components/pattern.rb +++ b/lib/simple_form/components/pattern.rb @@ -2,7 +2,7 @@ module SimpleForm module Components # Needs to be enabled in order to do automatic lookups. module Pattern - def pattern + def pattern(wrapper_options = nil) input_html_options[:pattern] ||= pattern_source nil end diff --git a/lib/simple_form/components/placeholders.rb b/lib/simple_form/components/placeholders.rb index 992044ed..9a7520e4 100644 --- a/lib/simple_form/components/placeholders.rb +++ b/lib/simple_form/components/placeholders.rb @@ -2,7 +2,7 @@ module SimpleForm module Components # Needs to be enabled in order to do automatic lookups. module Placeholders - def placeholder + def placeholder(wrapper_options = nil) input_html_options[:placeholder] ||= placeholder_text nil end diff --git a/lib/simple_form/components/readonly.rb b/lib/simple_form/components/readonly.rb index f4a986c2..37c2b385 100644 --- a/lib/simple_form/components/readonly.rb +++ b/lib/simple_form/components/readonly.rb @@ -2,7 +2,7 @@ module SimpleForm module Components # Needs to be enabled in order to do automatic lookups. module Readonly - def readonly + def readonly(wrapper_options = nil) if readonly_attribute? && !has_readonly? input_html_options[:readonly] ||= true input_html_classes << :readonly diff --git a/lib/simple_form/form_builder.rb b/lib/simple_form/form_builder.rb index 94641f92..81f775a8 100644 --- a/lib/simple_form/form_builder.rb +++ b/lib/simple_form/form_builder.rb @@ -106,7 +106,7 @@ module SimpleForm # Some inputs, as :time_zone and :country accepts a :priority option. If none is # given SimpleForm.time_zone_priority and SimpleForm.country_priority are used respectively. # - def input(attribute_name, options={}, &block) + def input(attribute_name, options = {}, &block) options = @defaults.deep_dup.deep_merge(options) if @defaults input = find_input(attribute_name, options, &block) @@ -130,14 +130,15 @@ module SimpleForm # # - def input_field(attribute_name, options={}) + def input_field(attribute_name, options = {}) options = options.dup options[:input_html] = options.except(:as, :boolean_style, :collection, :label_method, :value_method, *ATTRIBUTE_COMPONENTS) options = @defaults.deep_dup.deep_merge(options) if @defaults input = find_input(attribute_name, options) wrapper = find_wrapper(input.input_type, options) - components = (wrapper.components & ATTRIBUTE_COMPONENTS) + [:input] + components = (wrapper.components.map(&:namespace) & ATTRIBUTE_COMPONENTS) + [:input] + components = components.map { |component| SimpleForm::Wrappers::Leaf.new(component) } SimpleForm::Wrappers::Root.new(components, wrapper.options.merge(wrapper: false)).render input end @@ -170,7 +171,7 @@ module SimpleForm # # Please note that the association helper is currently only tested with Active Record. Depending on the ORM you are using your mileage may vary. # - def association(association, options={}, &block) + def association(association, options = {}, &block) options = options.dup return simple_fields_for(*[association, @@ -241,7 +242,7 @@ module SimpleForm # f.error :name # f.error :name, id: "cool_error" # - def error(attribute_name, options={}) + def error(attribute_name, options = {}) options = options.dup options[:error_html] = options.except(:error_tag, :error_prefix, :error_method) @@ -258,7 +259,7 @@ module SimpleForm # # f.full_error :token #=> Token is invalid # - def full_error(attribute_name, options={}) + def full_error(attribute_name, options = {}) options = options.dup options[:error_prefix] ||= if object.class.respond_to?(:human_attribute_name) @@ -280,7 +281,7 @@ module SimpleForm # f.hint :name, id: "cool_hint" # f.hint "Don't forget to accept this" # - def hint(attribute_name, options={}) + def hint(attribute_name, options = {}) options = options.dup options[:hint_html] = options.except(:hint_tag, :hint) @@ -331,7 +332,7 @@ module SimpleForm # f.error_notification message: 'Something went wrong' # f.error_notification id: 'user_error_message', class: 'form_error' # - def error_notification(options={}) + def error_notification(options = {}) SimpleForm::ErrorNotification.new(self, options).render end @@ -471,7 +472,7 @@ module SimpleForm private # Find an input based on the attribute name. - def find_input(attribute_name, options={}, &block) #:nodoc: + def find_input(attribute_name, options = {}, &block) #:nodoc: column = find_attribute_column(attribute_name) input_type = default_input_type(attribute_name, column, options) diff --git a/lib/simple_form/helpers.rb b/lib/simple_form/helpers.rb index 6567a7de..effeae5c 100644 --- a/lib/simple_form/helpers.rb +++ b/lib/simple_form/helpers.rb @@ -3,10 +3,10 @@ module SimpleForm # For instance, disabled cannot be turned on automatically, it requires the # user to explicitly pass the option disabled: true so it may work. module Helpers - autoload :Autofocus, 'simple_form/helpers/autofocus' - autoload :Disabled, 'simple_form/helpers/disabled' - autoload :Readonly, 'simple_form/helpers/readonly' - autoload :Required, 'simple_form/helpers/required' - autoload :Validators, 'simple_form/helpers/validators' + autoload :Autofocus, 'simple_form/helpers/autofocus' + autoload :Disabled, 'simple_form/helpers/disabled' + autoload :Readonly, 'simple_form/helpers/readonly' + autoload :Required, 'simple_form/helpers/required' + autoload :Validators, 'simple_form/helpers/validators' end end diff --git a/lib/simple_form/inputs/base.rb b/lib/simple_form/inputs/base.rb index e9eb3def..510d3766 100644 --- a/lib/simple_form/inputs/base.rb +++ b/lib/simple_form/inputs/base.rb @@ -79,7 +79,7 @@ module SimpleForm end end - def input + def input(wrapper_options = nil) raise NotImplementedError end @@ -167,7 +167,7 @@ module SimpleForm # email: 'E-mail.' # # Take a look at our locale example file. - def translate(namespace, default='') + def translate(namespace, default = '') model_names = lookup_model_names.dup lookups = [] @@ -184,6 +184,18 @@ module SimpleForm I18n.t(lookups.shift, scope: :"simple_form.#{namespace}", default: lookups).presence end + + def merge_wrapper_options(options, wrapper_options) + if wrapper_options + options.merge(wrapper_options) do |_, oldval, newval| + if Array === oldval + oldval + Array(newval) + end + end + else + options + end + end end end end diff --git a/lib/simple_form/inputs/block_input.rb b/lib/simple_form/inputs/block_input.rb index 483d393c..2bc2ff98 100644 --- a/lib/simple_form/inputs/block_input.rb +++ b/lib/simple_form/inputs/block_input.rb @@ -6,7 +6,7 @@ module SimpleForm @block = block end - def input + def input(wrapper_options = nil) template.capture(&@block) end end diff --git a/lib/simple_form/inputs/boolean_input.rb b/lib/simple_form/inputs/boolean_input.rb index b649685b..cf34f2e8 100644 --- a/lib/simple_form/inputs/boolean_input.rb +++ b/lib/simple_form/inputs/boolean_input.rb @@ -1,31 +1,36 @@ module SimpleForm module Inputs class BooleanInput < Base - def input + def input(wrapper_options = nil) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + if nested_boolean_style? build_hidden_field_for_checkbox + template.label_tag(nil, class: SimpleForm.boolean_label_class) { - build_check_box_without_hidden_field + inline_label + build_check_box_without_hidden_field(merged_input_options) + + inline_label } else - build_check_box + build_check_box(unchecked_value, merged_input_options) end end - def label_input + def label_input(wrapper_options = nil) if options[:label] == false - input + input(wrapper_options) elsif nested_boolean_style? html_options = label_html_options.dup html_options[:class] ||= [] html_options[:class].push(SimpleForm.boolean_label_class) if SimpleForm.boolean_label_class + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + build_hidden_field_for_checkbox + @builder.label(label_target, html_options) { - build_check_box_without_hidden_field + label_text + build_check_box_without_hidden_field(merged_input_options) + label_text } else - input + label + input(wrapper_options) + label(wrapper_options) end end @@ -35,14 +40,14 @@ module SimpleForm # reuse the method for nested boolean style, but with no unchecked value, # which won't generate the hidden checkbox. This is the default functionality # in Rails > 3.2.1, and is backported in SimpleForm AV helpers. - def build_check_box(unchecked_value = unchecked_value) + def build_check_box(unchecked_value, options) @builder.check_box(attribute_name, input_html_options, checked_value, unchecked_value) end # Build a checkbox without generating the hidden field. See # #build_hidden_field_for_checkbox for more info. - def build_check_box_without_hidden_field - build_check_box(nil) + def build_check_box_without_hidden_field(options) + build_check_box(nil, options) end # Create a hidden field for the current checkbox, so we can simulate Rails diff --git a/lib/simple_form/inputs/collection_input.rb b/lib/simple_form/inputs/collection_input.rb index 2b1eae56..db10abd9 100644 --- a/lib/simple_form/inputs/collection_input.rb +++ b/lib/simple_form/inputs/collection_input.rb @@ -12,7 +12,7 @@ module SimpleForm end end - def input + def input(wrapper_options = nil) raise NotImplementedError, "input should be implemented by classes inheriting from CollectionInput" end diff --git a/lib/simple_form/inputs/collection_radio_buttons_input.rb b/lib/simple_form/inputs/collection_radio_buttons_input.rb index 52d47785..b550f982 100644 --- a/lib/simple_form/inputs/collection_radio_buttons_input.rb +++ b/lib/simple_form/inputs/collection_radio_buttons_input.rb @@ -1,12 +1,15 @@ module SimpleForm module Inputs class CollectionRadioButtonsInput < CollectionInput - def input + def input(wrapper_options = nil) label_method, value_method = detect_collection_methods + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + @builder.send("collection_#{input_type}", attribute_name, collection, value_method, label_method, - input_options, input_html_options, &collection_block_for_nested_boolean_style + input_options, merged_input_options, + &collection_block_for_nested_boolean_style ) end diff --git a/lib/simple_form/inputs/collection_select_input.rb b/lib/simple_form/inputs/collection_select_input.rb index cb53d4ee..35f8978e 100644 --- a/lib/simple_form/inputs/collection_select_input.rb +++ b/lib/simple_form/inputs/collection_select_input.rb @@ -1,12 +1,14 @@ module SimpleForm module Inputs class CollectionSelectInput < CollectionInput - def input + def input(wrapper_options = nil) label_method, value_method = detect_collection_methods + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + @builder.collection_select( attribute_name, collection, value_method, label_method, - input_options, input_html_options + input_options, merged_input_options ) end end diff --git a/lib/simple_form/inputs/date_time_input.rb b/lib/simple_form/inputs/date_time_input.rb index 0414ad2f..27cf975e 100644 --- a/lib/simple_form/inputs/date_time_input.rb +++ b/lib/simple_form/inputs/date_time_input.rb @@ -1,11 +1,13 @@ module SimpleForm module Inputs class DateTimeInput < Base - def input + def input(wrapper_options = nil) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + if use_html5_inputs? - @builder.send(:"#{input_type}_field", attribute_name, input_html_options) + @builder.send(:"#{input_type}_field", attribute_name, merged_input_options) else - @builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options) + @builder.send(:"#{input_type}_select", attribute_name, input_options, merged_input_options) end end diff --git a/lib/simple_form/inputs/file_input.rb b/lib/simple_form/inputs/file_input.rb index a0ee2908..d964dd90 100644 --- a/lib/simple_form/inputs/file_input.rb +++ b/lib/simple_form/inputs/file_input.rb @@ -1,8 +1,10 @@ module SimpleForm module Inputs class FileInput < Base - def input - @builder.file_field(attribute_name, input_html_options) + def input(wrapper_options = nil) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + + @builder.file_field(attribute_name, merged_input_options) end end end diff --git a/lib/simple_form/inputs/grouped_collection_select_input.rb b/lib/simple_form/inputs/grouped_collection_select_input.rb index bd40ee53..d1cee8fe 100644 --- a/lib/simple_form/inputs/grouped_collection_select_input.rb +++ b/lib/simple_form/inputs/grouped_collection_select_input.rb @@ -1,11 +1,14 @@ module SimpleForm module Inputs class GroupedCollectionSelectInput < CollectionInput - def input + def input(wrapper_options = nil) label_method, value_method = detect_collection_methods + + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + @builder.grouped_collection_select(attribute_name, grouped_collection, group_method, group_label_method, value_method, label_method, - input_options, input_html_options) + input_options, merged_input_options) end private diff --git a/lib/simple_form/inputs/hidden_input.rb b/lib/simple_form/inputs/hidden_input.rb index 889d8d3d..53b6ad23 100644 --- a/lib/simple_form/inputs/hidden_input.rb +++ b/lib/simple_form/inputs/hidden_input.rb @@ -3,8 +3,10 @@ module SimpleForm class HiddenInput < Base disable :label, :errors, :hint, :required - def input - @builder.hidden_field(attribute_name, input_html_options) + def input(wrapper_options = nil) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + + @builder.hidden_field(attribute_name, merged_input_options) end private diff --git a/lib/simple_form/inputs/numeric_input.rb b/lib/simple_form/inputs/numeric_input.rb index ce0c3567..87b2ac91 100644 --- a/lib/simple_form/inputs/numeric_input.rb +++ b/lib/simple_form/inputs/numeric_input.rb @@ -3,16 +3,17 @@ module SimpleForm class NumericInput < Base enable :placeholder, :min_max - def input + def input(wrapper_options = nil) input_html_classes.unshift("numeric") if html5? input_html_options[:type] ||= "number" input_html_options[:step] ||= integer? ? 1 : "any" end - @builder.text_field(attribute_name, input_html_options) - end - private + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + + @builder.text_field(attribute_name, merged_input_options) + end end end end diff --git a/lib/simple_form/inputs/password_input.rb b/lib/simple_form/inputs/password_input.rb index 0a9a0ba6..0aa7385a 100644 --- a/lib/simple_form/inputs/password_input.rb +++ b/lib/simple_form/inputs/password_input.rb @@ -3,8 +3,10 @@ module SimpleForm class PasswordInput < Base enable :placeholder, :maxlength - def input - @builder.password_field(attribute_name, input_html_options) + def input(wrapper_options = nil) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + + @builder.password_field(attribute_name, merged_input_options) end end end diff --git a/lib/simple_form/inputs/priority_input.rb b/lib/simple_form/inputs/priority_input.rb index 19213dfd..c2272a3e 100644 --- a/lib/simple_form/inputs/priority_input.rb +++ b/lib/simple_form/inputs/priority_input.rb @@ -1,9 +1,11 @@ module SimpleForm module Inputs class PriorityInput < CollectionSelectInput - def input + def input(wrapper_options = nil) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + @builder.send(:"#{input_type}_select", attribute_name, input_priority, - input_options, input_html_options) + input_options, merged_input_options) end def input_priority diff --git a/lib/simple_form/inputs/range_input.rb b/lib/simple_form/inputs/range_input.rb index f231df33..00116fa3 100644 --- a/lib/simple_form/inputs/range_input.rb +++ b/lib/simple_form/inputs/range_input.rb @@ -1,7 +1,7 @@ module SimpleForm module Inputs class RangeInput < NumericInput - def input + def input(wrapper_options = nil) if html5? input_html_options[:type] ||= "range" input_html_options[:step] ||= 1 diff --git a/lib/simple_form/inputs/string_input.rb b/lib/simple_form/inputs/string_input.rb index 44ba6910..4752be92 100644 --- a/lib/simple_form/inputs/string_input.rb +++ b/lib/simple_form/inputs/string_input.rb @@ -3,13 +3,15 @@ module SimpleForm class StringInput < Base enable :placeholder, :maxlength, :pattern - def input + def input(wrapper_options = nil) unless string? input_html_classes.unshift("string") input_html_options[:type] ||= input_type if html5? end - @builder.text_field(attribute_name, input_html_options) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + + @builder.text_field(attribute_name, merged_input_options) end private diff --git a/lib/simple_form/inputs/text_input.rb b/lib/simple_form/inputs/text_input.rb index 8c840cba..d90eedac 100644 --- a/lib/simple_form/inputs/text_input.rb +++ b/lib/simple_form/inputs/text_input.rb @@ -3,8 +3,10 @@ module SimpleForm class TextInput < Base enable :placeholder, :maxlength - def input - @builder.text_area(attribute_name, input_html_options) + def input(wrapper_options = nil) + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + + @builder.text_area(attribute_name, merged_input_options) end end end diff --git a/lib/simple_form/wrappers.rb b/lib/simple_form/wrappers.rb index 20241e4c..8aa11e92 100644 --- a/lib/simple_form/wrappers.rb +++ b/lib/simple_form/wrappers.rb @@ -4,5 +4,6 @@ module SimpleForm autoload :Many, 'simple_form/wrappers/many' autoload :Root, 'simple_form/wrappers/root' autoload :Single, 'simple_form/wrappers/single' + autoload :Leaf, 'simple_form/wrappers/leaf' end end diff --git a/lib/simple_form/wrappers/builder.rb b/lib/simple_form/wrappers/builder.rb index 6a00f4f2..0889ad10 100644 --- a/lib/simple_form/wrappers/builder.rb +++ b/lib/simple_form/wrappers/builder.rb @@ -45,20 +45,20 @@ module SimpleForm @components = [] end - def use(name, options=nil, &block) + def use(name, options = {}, &block) if options && wrapper = options[:wrap_with] - @components << Single.new(name, wrapper) + @components << Single.new(name, wrapper, options.except(:wrap_with)) else - @components << name + @components << Leaf.new(name, options) end end - def optional(name, options=nil, &block) + def optional(name, options = {}, &block) @options[name] = false use(name, options, &block) end - def wrapper(name, options=nil) + def wrapper(name, options = nil) if block_given? name, options = nil, name if name.is_a?(Hash) builder = self.class.new(@options) diff --git a/lib/simple_form/wrappers/leaf.rb b/lib/simple_form/wrappers/leaf.rb new file mode 100644 index 00000000..b2ecfbe6 --- /dev/null +++ b/lib/simple_form/wrappers/leaf.rb @@ -0,0 +1,28 @@ +module SimpleForm + module Wrappers + class Leaf + attr_reader :namespace + + def initialize(namespace, options = {}) + @namespace = namespace + @options = options + end + + def render(input) + method = input.method(@namespace) + + if method.arity == 0 + ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: @namespace }) + + method.call + else + method.call(@options) + end + end + + def find(name) + return self if @namespace == name + end + end + end +end diff --git a/lib/simple_form/wrappers/many.rb b/lib/simple_form/wrappers/many.rb index 93819717..fcfbafff 100644 --- a/lib/simple_form/wrappers/many.rb +++ b/lib/simple_form/wrappers/many.rb @@ -1,7 +1,7 @@ module SimpleForm module Wrappers # A wrapper is an object that holds several components and render them. - # A component may either be a symbol or any object that responds to `render`. + # A component may be any object that responds to `render`. # This API allows inputs/components to be easily wrapped, removing the # need to modify the code only to wrap input in an extra tag. # @@ -12,7 +12,7 @@ module SimpleForm attr_reader :namespace, :defaults, :components alias :to_sym :namespace - def initialize(namespace, components, defaults={}) + def initialize(namespace, components, defaults = {}) @namespace = namespace @components = components @defaults = defaults @@ -25,8 +25,8 @@ module SimpleForm options = input.options components.each do |component| - next if options[component] == false - rendered = component.respond_to?(:render) ? component.render(input) : input.send(component) + next if options[component.namespace] == false + rendered = component.render(input) content.safe_concat rendered.to_s if rendered end diff --git a/lib/simple_form/wrappers/single.rb b/lib/simple_form/wrappers/single.rb index eda04208..77a6daf3 100644 --- a/lib/simple_form/wrappers/single.rb +++ b/lib/simple_form/wrappers/single.rb @@ -2,20 +2,24 @@ module SimpleForm module Wrappers # `Single` is an optimization for a wrapper that has only one component. class Single < Many - def initialize(name, options={}) - super(name, [name], options) + def initialize(name, wrapper_options = {}, options = {}) + super(name, [Leaf.new(name, options)], wrapper_options) end def render(input) options = input.options if options[namespace] != false - content = input.send(namespace) + content = component.render(input) wrap(input, options, content) if content end end private + def component + components.first + end + def html_options(options) [:label, :input].include?(namespace) ? {} : super end diff --git a/test/action_view_extensions/builder_test.rb b/test/action_view_extensions/builder_test.rb index 12766408..bb45b8ad 100644 --- a/test/action_view_extensions/builder_test.rb +++ b/test/action_view_extensions/builder_test.rb @@ -8,13 +8,13 @@ class BuilderTest < ActionView::TestCase end end - def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block) + def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options = {}, html_options = {}, &block) with_concat_form_for(object) do |f| f.collection_radio_buttons attribute, collection, value_method, text_method, options, html_options, &block end end - def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block) + def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options = {}, html_options = {}, &block) with_concat_form_for(object) do |f| f.collection_check_boxes attribute, collection, value_method, text_method, options, html_options, &block end diff --git a/test/components/label_test.rb b/test/components/label_test.rb index 01c6e546..56637daa 100644 --- a/test/components/label_test.rb +++ b/test/components/label_test.rb @@ -7,7 +7,7 @@ class IsolatedLabelTest < ActionView::TestCase SimpleForm::Inputs::Base.reset_i18n_cache :translate_required_html end - def with_label_for(object, attribute_name, type, options={}) + def with_label_for(object, attribute_name, type, options = {}) with_concat_form_for(object) do |f| options[:reflection] = Association.new(Company, :company, {}) if options.delete(:setup_association) SimpleForm::Inputs::Base.new(f, attribute_name, nil, type, options).label diff --git a/test/form_builder/error_notification_test.rb b/test/form_builder/error_notification_test.rb index ad04e19f..751efbe9 100644 --- a/test/form_builder/error_notification_test.rb +++ b/test/form_builder/error_notification_test.rb @@ -3,7 +3,7 @@ require 'test_helper' # Tests for f.error_notification class ErrorNotificationTest < ActionView::TestCase - def with_error_notification_for(object, options={}, &block) + def with_error_notification_for(object, options = {}, &block) with_concat_form_for(object) do |f| f.error_notification(options) end diff --git a/test/form_builder/wrapper_test.rb b/test/form_builder/wrapper_test.rb index fa27204b..a7bd5b72 100644 --- a/test/form_builder/wrapper_test.rb +++ b/test/form_builder/wrapper_test.rb @@ -211,4 +211,45 @@ class WrapperTest < ActionView::TestCase assert_select "section.custom_wrapper div.another_wrapper label" assert_select "section.custom_wrapper div.another_wrapper input.string" end + + test 'input accepts attributes in the DSL' do + swap_wrapper :default, self.custom_wrapper_with_input_class do + with_concat_form_for @user do |f| + concat f.input :name + end + end + + assert_select "div.custom_wrapper input.string.inline-class" + end + + test 'label accepts attributes in the DSL' do + swap_wrapper :default, self.custom_wrapper_with_label_class do + with_concat_form_for @user do |f| + concat f.input :name + end + end + + assert_select "div.custom_wrapper label.string.inline-class" + end + + test 'label_input accepts attributes in the DSL' do + swap_wrapper :default, self.custom_wrapper_with_label_input_class do + with_concat_form_for @user do |f| + concat f.input :name + end + end + + assert_select "div.custom_wrapper label.string.inline-class" + assert_select "div.custom_wrapper input.string.inline-class" + end + + test 'input accepts data attributes in the DSL' do + swap_wrapper :default, self.custom_wrapper_with_input_attributes do + with_concat_form_for @user do |f| + concat f.input :name + end + end + + assert_select "div.custom_wrapper input.string[data-modal=true]" + end end diff --git a/test/inputs/discovery_test.rb b/test/inputs/discovery_test.rb index 307c5461..6103f9ba 100644 --- a/test/inputs/discovery_test.rb +++ b/test/inputs/discovery_test.rb @@ -2,7 +2,7 @@ require 'test_helper' class DiscoveryTest < ActionView::TestCase # Setup new inputs and remove them after the test. - def discovery(value=false) + def discovery(value = false) swap SimpleForm, cache_discovery: value do begin load "support/discovery_inputs.rb" @@ -12,6 +12,7 @@ class DiscoveryTest < ActionView::TestCase Object.send :remove_const, :StringInput Object.send :remove_const, :NumericInput Object.send :remove_const, :CustomizedInput + Object.send :remove_const, :DeprecatedInput Object.send :remove_const, :CollectionSelectInput end end @@ -66,4 +67,14 @@ class DiscoveryTest < ActionView::TestCase assert_select 'form select#user_active.select.chosen' end end + + test 'inputs method without wrapper_options are deprecated' do + discovery do + assert_deprecated do + with_form_for @user, :name, as: :deprecated + end + + assert_select 'form section input#user_name.string' + end + end end diff --git a/test/support/discovery_inputs.rb b/test/support/discovery_inputs.rb index 167f33dc..eebf4db8 100644 --- a/test/support/discovery_inputs.rb +++ b/test/support/discovery_inputs.rb @@ -1,16 +1,26 @@ class StringInput < SimpleForm::Inputs::StringInput - def input + def input(wrapper_options = nil) "
#{super}
".html_safe end end class NumericInput < SimpleForm::Inputs::NumericInput - def input + def input(wrapper_options = nil) "
#{super}
".html_safe end end class CustomizedInput < SimpleForm::Inputs::StringInput + def input(wrapper_options = nil) + "
#{super}
".html_safe + end + + def input_method + :text_field + end +end + +class DeprecatedInput < SimpleForm::Inputs::StringInput def input "
#{super}
".html_safe end diff --git a/test/support/misc_helpers.rb b/test/support/misc_helpers.rb index 5ddac2c3..61b03d55 100644 --- a/test/support/misc_helpers.rb +++ b/test/support/misc_helpers.rb @@ -46,7 +46,7 @@ module MiscHelpers end end - def swap_wrapper(name=:default, wrapper=self.custom_wrapper) + def swap_wrapper(name = :default, wrapper = self.custom_wrapper) old = SimpleForm.wrappers[name] SimpleForm.wrappers[name] = wrapper yield @@ -68,6 +68,32 @@ module MiscHelpers end end + def custom_wrapper_with_input_class + SimpleForm.build tag: :div, class: "custom_wrapper" do |b| + b.use :label + b.use :input, class: 'inline-class' + end + end + + def custom_wrapper_with_label_class + SimpleForm.build tag: :div, class: "custom_wrapper" do |b| + b.use :label, class: 'inline-class' + b.use :input + end + end + + def custom_wrapper_with_input_attributes + SimpleForm.build tag: :div, class: "custom_wrapper" do |b| + b.use :input, data: { modal: true } + end + end + + def custom_wrapper_with_label_input_class + SimpleForm.build tag: :div, class: "custom_wrapper" do |b| + b.use :label_input, class: 'inline-class' + end + end + def custom_wrapper_with_wrapped_input SimpleForm.build tag: :div, class: "custom_wrapper" do |b| b.wrapper tag: :div, class: 'elem' do |component| @@ -142,7 +168,7 @@ module MiscHelpers end end - def with_input_for(object, attribute_name, type, options={}) + def with_input_for(object, attribute_name, type, options = {}) with_concat_form_for(object) do |f| f.input(attribute_name, options.merge(as: type)) end diff --git a/test/support/models.rb b/test/support/models.rb index 531aee58..77197ae7 100644 --- a/test/support/models.rb +++ b/test/support/models.rb @@ -66,7 +66,7 @@ class User new attributes end - def initialize(options={}) + def initialize(options = {}) @new_record = false options.each do |key, value| send("#{key}=", value)