simple_form 2.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +77 -33
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +387 -187
  5. data/lib/generators/simple_form/install_generator.rb +4 -4
  6. data/lib/generators/simple_form/templates/README +3 -4
  7. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +45 -22
  8. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +128 -24
  9. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +87 -6
  10. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
  11. data/lib/simple_form/action_view_extensions/builder.rb +2 -319
  12. data/lib/simple_form/action_view_extensions/form_helper.rb +8 -11
  13. data/lib/simple_form/components/errors.rb +28 -2
  14. data/lib/simple_form/components/hints.rb +8 -3
  15. data/lib/simple_form/components/html5.rb +6 -3
  16. data/lib/simple_form/components/label_input.rb +20 -2
  17. data/lib/simple_form/components/labels.rb +14 -10
  18. data/lib/simple_form/components/maxlength.rb +2 -9
  19. data/lib/simple_form/components/min_max.rb +1 -1
  20. data/lib/simple_form/components/pattern.rb +3 -3
  21. data/lib/simple_form/components/placeholders.rb +2 -2
  22. data/lib/simple_form/components/readonly.rb +1 -1
  23. data/lib/simple_form/components.rb +1 -1
  24. data/lib/simple_form/error_notification.rb +2 -2
  25. data/lib/simple_form/form_builder.rb +262 -107
  26. data/lib/simple_form/helpers.rb +6 -6
  27. data/lib/simple_form/inputs/base.rb +37 -16
  28. data/lib/simple_form/inputs/block_input.rb +2 -2
  29. data/lib/simple_form/inputs/boolean_input.rb +33 -18
  30. data/lib/simple_form/inputs/collection_input.rb +34 -13
  31. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +7 -12
  32. data/lib/simple_form/inputs/collection_select_input.rb +4 -2
  33. data/lib/simple_form/inputs/date_time_input.rb +23 -9
  34. data/lib/simple_form/inputs/file_input.rb +4 -2
  35. data/lib/simple_form/inputs/grouped_collection_select_input.rb +15 -3
  36. data/lib/simple_form/inputs/hidden_input.rb +4 -2
  37. data/lib/simple_form/inputs/numeric_input.rb +3 -8
  38. data/lib/simple_form/inputs/password_input.rb +4 -3
  39. data/lib/simple_form/inputs/priority_input.rb +4 -2
  40. data/lib/simple_form/inputs/range_input.rb +1 -1
  41. data/lib/simple_form/inputs/string_input.rb +4 -3
  42. data/lib/simple_form/inputs/text_input.rb +4 -2
  43. data/lib/simple_form/railtie.rb +14 -0
  44. data/lib/simple_form/tags.rb +68 -0
  45. data/lib/simple_form/version.rb +1 -1
  46. data/lib/simple_form/wrappers/builder.rb +11 -35
  47. data/lib/simple_form/wrappers/leaf.rb +28 -0
  48. data/lib/simple_form/wrappers/many.rb +7 -7
  49. data/lib/simple_form/wrappers/root.rb +2 -2
  50. data/lib/simple_form/wrappers/single.rb +5 -3
  51. data/lib/simple_form/wrappers.rb +2 -1
  52. data/lib/simple_form.rb +99 -52
  53. data/test/action_view_extensions/builder_test.rb +113 -127
  54. data/test/action_view_extensions/form_helper_test.rb +58 -30
  55. data/test/components/label_test.rb +83 -83
  56. data/test/form_builder/association_test.rb +96 -61
  57. data/test/form_builder/button_test.rb +14 -14
  58. data/test/form_builder/error_notification_test.rb +9 -9
  59. data/test/form_builder/error_test.rb +159 -34
  60. data/test/form_builder/general_test.rb +176 -121
  61. data/test/form_builder/hint_test.rb +43 -37
  62. data/test/form_builder/input_field_test.rb +99 -52
  63. data/test/form_builder/label_test.rb +67 -15
  64. data/test/form_builder/wrapper_test.rb +157 -41
  65. data/test/generators/simple_form_generator_test.rb +4 -4
  66. data/test/inputs/boolean_input_test.rb +92 -24
  67. data/test/inputs/collection_check_boxes_input_test.rb +150 -71
  68. data/test/inputs/collection_radio_buttons_input_test.rb +213 -113
  69. data/test/inputs/collection_select_input_test.rb +221 -85
  70. data/test/inputs/datetime_input_test.rb +125 -47
  71. data/test/inputs/disabled_test.rb +25 -25
  72. data/test/inputs/discovery_test.rb +60 -10
  73. data/test/inputs/file_input_test.rb +3 -3
  74. data/test/inputs/general_test.rb +48 -32
  75. data/test/inputs/grouped_collection_select_input_test.rb +76 -27
  76. data/test/inputs/hidden_input_test.rb +6 -5
  77. data/test/inputs/numeric_input_test.rb +46 -46
  78. data/test/inputs/priority_input_test.rb +21 -15
  79. data/test/inputs/readonly_test.rb +31 -31
  80. data/test/inputs/required_test.rb +30 -18
  81. data/test/inputs/string_input_test.rb +53 -52
  82. data/test/inputs/text_input_test.rb +15 -8
  83. data/test/simple_form_test.rb +8 -0
  84. data/test/support/discovery_inputs.rb +32 -2
  85. data/test/support/misc_helpers.rb +130 -29
  86. data/test/support/mock_controller.rb +6 -6
  87. data/test/support/models.rb +125 -71
  88. data/test/test_helper.rb +28 -35
  89. metadata +17 -29
  90. data/lib/simple_form/action_view_extensions/builder.rb.orig +0 -247
  91. data/lib/simple_form/core_ext/hash.rb +0 -16
  92. data/lib/simple_form/form_builder.rb.orig +0 -486
  93. data/lib/simple_form/version.rb.orig +0 -7
@@ -1,8 +1,13 @@
1
1
  require 'simple_form/i18n_cache'
2
+ require 'active_support/core_ext/string/output_safety'
3
+ require 'action_view/helpers'
2
4
 
3
5
  module SimpleForm
4
6
  module Inputs
5
7
  class Base
8
+ include ERB::Util
9
+ include ActionView::Helpers::TranslationHelper
10
+
6
11
  extend I18nCache
7
12
 
8
13
  include SimpleForm::Helpers::Autofocus
@@ -24,7 +29,7 @@ module SimpleForm
24
29
  attr_reader :attribute_name, :column, :input_type, :reflection,
25
30
  :options, :input_html_options, :input_html_classes, :html_classes
26
31
 
27
- delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, :to => :@builder
32
+ delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, to: :@builder
28
33
 
29
34
  class_attribute :default_options
30
35
  self.default_options = {}
@@ -50,14 +55,14 @@ module SimpleForm
50
55
  def initialize(builder, attribute_name, column, input_type, options = {})
51
56
  super
52
57
 
53
- options = options.dup
54
- @builder = builder
55
- @attribute_name = attribute_name
56
- @column = column
57
- @input_type = input_type
58
- @reflection = options.delete(:reflection)
59
- @options = options.reverse_merge!(self.class.default_options)
60
- @required = calculate_required
58
+ options = options.dup
59
+ @builder = builder
60
+ @attribute_name = attribute_name
61
+ @column = column
62
+ @input_type = input_type
63
+ @reflection = options.delete(:reflection)
64
+ @options = options.reverse_merge!(self.class.default_options)
65
+ @required = calculate_required
61
66
 
62
67
  # Notice that html_options_for receives a reference to input_html_classes.
63
68
  # This means that classes added dynamically to input_html_classes will
@@ -65,6 +70,10 @@ module SimpleForm
65
70
  @html_classes = SimpleForm.additional_classes_for(:input) { additional_classes }
66
71
 
67
72
  @input_html_classes = @html_classes.dup
73
+ if SimpleForm.input_class && !input_html_classes.empty?
74
+ input_html_classes << SimpleForm.input_class
75
+ end
76
+
68
77
  @input_html_options = html_options_for(:input, input_html_classes).tap do |o|
69
78
  o[:readonly] = true if has_readonly?
70
79
  o[:disabled] = true if has_disabled?
@@ -72,7 +81,7 @@ module SimpleForm
72
81
  end
73
82
  end
74
83
 
75
- def input
84
+ def input(wrapper_options = nil)
76
85
  raise NotImplementedError
77
86
  end
78
87
 
@@ -90,10 +99,6 @@ module SimpleForm
90
99
 
91
100
  private
92
101
 
93
- def add_size!
94
- input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
95
- end
96
-
97
102
  def limit
98
103
  if column
99
104
  decimal_or_float? ? decimal_limit : column_limit
@@ -164,7 +169,7 @@ module SimpleForm
164
169
  # email: 'E-mail.'
165
170
  #
166
171
  # Take a look at our locale example file.
167
- def translate(namespace, default='')
172
+ def translate_from_namespace(namespace, default = '')
168
173
  model_names = lookup_model_names.dup
169
174
  lookups = []
170
175
 
@@ -179,7 +184,23 @@ module SimpleForm
179
184
  lookups << :"defaults.#{reflection_or_attribute_name}"
180
185
  lookups << default
181
186
 
182
- I18n.t(lookups.shift, :scope => :"simple_form.#{namespace}", :default => lookups).presence
187
+ I18n.t(lookups.shift, scope: :"#{i18n_scope}.#{namespace}", default: lookups).presence
188
+ end
189
+
190
+ def merge_wrapper_options(options, wrapper_options)
191
+ if wrapper_options
192
+ options.merge(wrapper_options) do |_, oldval, newval|
193
+ if Array === oldval
194
+ oldval + Array(newval)
195
+ end
196
+ end
197
+ else
198
+ options
199
+ end
200
+ end
201
+
202
+ def i18n_scope
203
+ SimpleForm.i18n_scope
183
204
  end
184
205
  end
185
206
  end
@@ -6,9 +6,9 @@ module SimpleForm
6
6
  @block = block
7
7
  end
8
8
 
9
- def input
9
+ def input(wrapper_options = nil)
10
10
  template.capture(&@block)
11
11
  end
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -1,30 +1,36 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class BooleanInput < Base
4
- def input
4
+ def input(wrapper_options = nil)
5
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
6
+
5
7
  if nested_boolean_style?
6
8
  build_hidden_field_for_checkbox +
7
- template.label_tag(nil, :class => "checkbox") {
8
- build_check_box_without_hidden_field + inline_label
9
+ template.label_tag(nil, class: SimpleForm.boolean_label_class) {
10
+ build_check_box_without_hidden_field(merged_input_options) +
11
+ inline_label
9
12
  }
10
13
  else
11
- build_check_box
14
+ build_check_box(unchecked_value, merged_input_options)
12
15
  end
13
16
  end
14
17
 
15
- def label_input
16
- if options[:label] == false
17
- input
18
+ def label_input(wrapper_options = nil)
19
+ if options[:label] == false || inline_label?
20
+ input(wrapper_options)
18
21
  elsif nested_boolean_style?
19
22
  html_options = label_html_options.dup
20
- html_options[:class].push(:checkbox)
23
+ html_options[:class] ||= []
24
+ html_options[:class].push(SimpleForm.boolean_label_class) if SimpleForm.boolean_label_class
25
+
26
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
21
27
 
22
28
  build_hidden_field_for_checkbox +
23
29
  @builder.label(label_target, html_options) {
24
- build_check_box_without_hidden_field + label_text
30
+ build_check_box_without_hidden_field(merged_input_options) + label_text
25
31
  }
26
32
  else
27
- input + label
33
+ input(wrapper_options) + label(wrapper_options)
28
34
  end
29
35
  end
30
36
 
@@ -34,14 +40,14 @@ module SimpleForm
34
40
  # reuse the method for nested boolean style, but with no unchecked value,
35
41
  # which won't generate the hidden checkbox. This is the default functionality
36
42
  # in Rails > 3.2.1, and is backported in SimpleForm AV helpers.
37
- def build_check_box(unchecked_value = unchecked_value)
38
- @builder.check_box(attribute_name, input_html_options, checked_value, unchecked_value)
43
+ def build_check_box(unchecked_value, options)
44
+ @builder.check_box(attribute_name, options, checked_value, unchecked_value)
39
45
  end
40
46
 
41
47
  # Build a checkbox without generating the hidden field. See
42
48
  # #build_hidden_field_for_checkbox for more info.
43
- def build_check_box_without_hidden_field
44
- build_check_box(nil)
49
+ def build_check_box_without_hidden_field(options)
50
+ build_check_box(nil, options)
45
51
  end
46
52
 
47
53
  # Create a hidden field for the current checkbox, so we can simulate Rails
@@ -49,14 +55,23 @@ module SimpleForm
49
55
  # we need the hidden field to be *outside* the label (otherwise it
50
56
  # generates invalid html - html5 only).
51
57
  def build_hidden_field_for_checkbox
52
- @builder.hidden_field(attribute_name, :value => unchecked_value, :id => nil,
53
- :disabled => input_html_options[:disabled],
54
- :name => input_html_options[:name])
58
+ options = { value: unchecked_value, id: nil, disabled: input_html_options[:disabled] }
59
+ options[:name] = input_html_options[:name] if input_html_options.has_key?(:name)
60
+
61
+ @builder.hidden_field(attribute_name, options)
62
+ end
63
+
64
+ def inline_label?
65
+ nested_boolean_style? && options[:inline_label]
55
66
  end
56
67
 
57
68
  def inline_label
58
69
  inline_option = options[:inline_label]
59
- inline_option == true ? label_text : inline_option
70
+
71
+ if inline_option
72
+ label = inline_option == true ? label_text : html_escape(inline_option)
73
+ " #{label}".html_safe
74
+ end
60
75
  end
61
76
 
62
77
  # Booleans are not required by default because in most of the cases
@@ -7,19 +7,23 @@ module SimpleForm
7
7
  # "simple_form.no" keys. See the example locale file.
8
8
  def self.boolean_collection
9
9
  i18n_cache :boolean_collection do
10
- [ [I18n.t(:"simple_form.yes", :default => 'Yes'), true],
11
- [I18n.t(:"simple_form.no", :default => 'No'), false] ]
10
+ [ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
11
+ [I18n.t(:"simple_form.no", default: 'No'), false] ]
12
12
  end
13
13
  end
14
14
 
15
- def input
15
+ def input(wrapper_options = nil)
16
16
  raise NotImplementedError,
17
17
  "input should be implemented by classes inheriting from CollectionInput"
18
18
  end
19
19
 
20
20
  def input_options
21
21
  options = super
22
+
22
23
  options[:include_blank] = true unless skip_include_blank?
24
+ translate_option options, :prompt
25
+ translate_option options, :include_blank
26
+
23
27
  options
24
28
  end
25
29
 
@@ -33,7 +37,7 @@ module SimpleForm
33
37
  end
34
38
 
35
39
  def has_required?
36
- super && (input_options[:include_blank] || multiple?)
40
+ super && (input_options[:include_blank] || input_options[:prompt] || multiple?)
37
41
  end
38
42
 
39
43
  # Check if :include_blank must be included by default.
@@ -66,17 +70,21 @@ module SimpleForm
66
70
  collection_translated = translate_collection if collection_classes == [Symbol]
67
71
 
68
72
  if collection_translated || collection_classes.include?(Array)
69
- { :label => :first, :value => :last }
73
+ { label: :first, value: :second }
70
74
  elsif collection_includes_basic_objects?(collection_classes)
71
- { :label => :to_s, :value => :to_s }
75
+ { label: :to_s, value: :to_s }
72
76
  else
73
- sample = collection.first || collection.last
74
-
75
- { :label => SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) },
76
- :value => SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) } }
77
+ detect_method_from_class(collection_classes)
77
78
  end
78
79
  end
79
80
 
81
+ def detect_method_from_class(collection_classes)
82
+ sample = collection.first || collection.last
83
+
84
+ { label: SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) },
85
+ value: SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) } }
86
+ end
87
+
80
88
  def detect_collection_classes(some_collection = collection)
81
89
  some_collection.map { |e| e.class }.uniq
82
90
  end
@@ -88,14 +96,27 @@ module SimpleForm
88
96
  end
89
97
 
90
98
  def translate_collection
91
- if translated_collection = translate(:options)
99
+ if translated_collection = translate_from_namespace(:options)
92
100
  @collection = collection.map do |key|
93
- [translated_collection[key] || key, key]
101
+ html_key = "#{key}_html".to_sym
102
+
103
+ if translated_collection[html_key]
104
+ [translated_collection[html_key].html_safe || key, key.to_s]
105
+ else
106
+ [translated_collection[key] || key, key.to_s]
107
+ end
94
108
  end
95
109
  true
96
110
  end
97
111
  end
112
+
113
+ def translate_option(options, key)
114
+ if options[key] == :translate
115
+ namespace = key.to_s.pluralize
116
+
117
+ options[key] = translate_from_namespace(namespace, true)
118
+ end
119
+ end
98
120
  end
99
121
  end
100
122
  end
101
-
@@ -1,19 +1,21 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class CollectionRadioButtonsInput < CollectionInput
4
- def input
4
+ def input(wrapper_options = nil)
5
5
  label_method, value_method = detect_collection_methods
6
6
 
7
- @builder.send("collection_#{input_type}",
7
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
8
+
9
+ @builder.send(:"collection_#{input_type}",
8
10
  attribute_name, collection, value_method, label_method,
9
- input_options, input_html_options, &collection_block_for_nested_boolean_style
11
+ input_options, merged_input_options,
12
+ &collection_block_for_nested_boolean_style
10
13
  )
11
14
  end
12
15
 
13
16
  def input_options
14
17
  options = super
15
18
  apply_default_collection_options!(options)
16
- apply_nested_boolean_collection_options!(options) if nested_boolean_style?
17
19
  options
18
20
  end
19
21
 
@@ -23,7 +25,7 @@ module SimpleForm
23
25
  options[:item_wrapper_tag] ||= options.fetch(:item_wrapper_tag, SimpleForm.item_wrapper_tag)
24
26
  options[:item_wrapper_class] = [
25
27
  item_wrapper_class, options[:item_wrapper_class], SimpleForm.item_wrapper_class
26
- ].compact.presence
28
+ ].compact.presence if SimpleForm.include_default_input_wrapper_class
27
29
 
28
30
  options[:collection_wrapper_tag] ||= options.fetch(:collection_wrapper_tag, SimpleForm.collection_wrapper_tag)
29
31
  options[:collection_wrapper_class] = [
@@ -31,13 +33,6 @@ module SimpleForm
31
33
  ].compact.presence
32
34
  end
33
35
 
34
- # Force item wrapper to be a label when using nested boolean, to support
35
- # configuring classes through :item_wrapper_class, and to maintain
36
- # compatibility with :inline style and default :item_wrapper_tag.
37
- def apply_nested_boolean_collection_options!(options)
38
- options[:item_wrapper_tag] = :label
39
- end
40
-
41
36
  def collection_block_for_nested_boolean_style
42
37
  return unless nested_boolean_style?
43
38
 
@@ -1,12 +1,14 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class CollectionSelectInput < CollectionInput
4
- def input
4
+ def input(wrapper_options = nil)
5
5
  label_method, value_method = detect_collection_methods
6
6
 
7
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
8
+
7
9
  @builder.collection_select(
8
10
  attribute_name, collection, value_method, label_method,
9
- input_options, input_html_options
11
+ input_options, merged_input_options
10
12
  )
11
13
  end
12
14
  end
@@ -1,23 +1,37 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class DateTimeInput < Base
4
- def input
5
- @builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options)
4
+ def input(wrapper_options = nil)
5
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
6
+
7
+ if use_html5_inputs?
8
+ @builder.send(:"#{input_type}_field", attribute_name, merged_input_options)
9
+ else
10
+ @builder.send(:"#{input_type}_select", attribute_name, input_options, merged_input_options)
11
+ end
6
12
  end
7
13
 
8
14
  private
9
15
 
10
16
  def label_target
11
- position = case input_type
12
- when :date, :datetime
13
- date_order = input_options[:order] || I18n.t('date.order')
14
- date_order.first
17
+ if use_html5_inputs?
18
+ attribute_name
15
19
  else
16
- :hour
20
+ position = case input_type
21
+ when :date, :datetime
22
+ date_order = input_options[:order] || I18n.t('date.order')
23
+ date_order.first.to_sym
24
+ else
25
+ :hour
26
+ end
27
+
28
+ position = ActionView::Helpers::DateTimeSelector::POSITION[position]
29
+ "#{attribute_name}_#{position}i"
17
30
  end
31
+ end
18
32
 
19
- position = ActionView::Helpers::DateTimeSelector::POSITION[position]
20
- "#{attribute_name}_#{position}i"
33
+ def use_html5_inputs?
34
+ input_options[:html5]
21
35
  end
22
36
  end
23
37
  end
@@ -1,8 +1,10 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class FileInput < Base
4
- def input
5
- @builder.file_field(attribute_name, input_html_options)
4
+ def input(wrapper_options = nil)
5
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
6
+
7
+ @builder.file_field(attribute_name, merged_input_options)
6
8
  end
7
9
  end
8
10
  end
@@ -1,11 +1,14 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class GroupedCollectionSelectInput < CollectionInput
4
- def input
4
+ def input(wrapper_options = nil)
5
5
  label_method, value_method = detect_collection_methods
6
+
7
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
8
+
6
9
  @builder.grouped_collection_select(attribute_name, grouped_collection,
7
10
  group_method, group_label_method, value_method, label_method,
8
- input_options, input_html_options)
11
+ input_options, merged_input_options)
9
12
  end
10
13
 
11
14
  private
@@ -19,7 +22,7 @@ module SimpleForm
19
22
 
20
23
  # Sample collection
21
24
  def collection
22
- @collection ||= grouped_collection.first.try(:send, group_method) || []
25
+ @collection ||= grouped_collection.map { |collection| collection.try(:send, group_method) }.detect(&:present?) || []
23
26
  end
24
27
 
25
28
  def group_method
@@ -36,6 +39,15 @@ module SimpleForm
36
39
 
37
40
  label
38
41
  end
42
+
43
+ def detect_method_from_class(collection_classes)
44
+ return {} if collection_classes.empty?
45
+
46
+ sample = collection_classes.first
47
+
48
+ { label: SimpleForm.collection_label_methods.find { |m| sample.instance_methods.include?(m) },
49
+ value: SimpleForm.collection_value_methods.find { |m| sample.instance_methods.include?(m) } }
50
+ end
39
51
  end
40
52
  end
41
53
  end
@@ -3,8 +3,10 @@ module SimpleForm
3
3
  class HiddenInput < Base
4
4
  disable :label, :errors, :hint, :required
5
5
 
6
- def input
7
- @builder.hidden_field(attribute_name, input_html_options)
6
+ def input(wrapper_options = nil)
7
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
8
+
9
+ @builder.hidden_field(attribute_name, merged_input_options)
8
10
  end
9
11
 
10
12
  private
@@ -3,21 +3,16 @@ module SimpleForm
3
3
  class NumericInput < Base
4
4
  enable :placeholder, :min_max
5
5
 
6
- def input
7
- add_size!
6
+ def input(wrapper_options = nil)
8
7
  input_html_classes.unshift("numeric")
9
8
  if html5?
10
9
  input_html_options[:type] ||= "number"
11
10
  input_html_options[:step] ||= integer? ? 1 : "any"
12
11
  end
13
- @builder.text_field(attribute_name, input_html_options)
14
- end
15
12
 
16
- private
13
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
17
14
 
18
- # Rails adds the size attr by default, if the :size key does not exist.
19
- def add_size!
20
- input_html_options[:size] ||= nil
15
+ @builder.text_field(attribute_name, merged_input_options)
21
16
  end
22
17
  end
23
18
  end
@@ -3,9 +3,10 @@ module SimpleForm
3
3
  class PasswordInput < Base
4
4
  enable :placeholder, :maxlength
5
5
 
6
- def input
7
- add_size!
8
- @builder.password_field(attribute_name, input_html_options)
6
+ def input(wrapper_options = nil)
7
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
8
+
9
+ @builder.password_field(attribute_name, merged_input_options)
9
10
  end
10
11
  end
11
12
  end
@@ -1,9 +1,11 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class PriorityInput < CollectionSelectInput
4
- def input
4
+ def input(wrapper_options = nil)
5
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
6
+
5
7
  @builder.send(:"#{input_type}_select", attribute_name, input_priority,
6
- input_options, input_html_options)
8
+ input_options, merged_input_options)
7
9
  end
8
10
 
9
11
  def input_priority
@@ -1,7 +1,7 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class RangeInput < NumericInput
4
- def input
4
+ def input(wrapper_options = nil)
5
5
  if html5?
6
6
  input_html_options[:type] ||= "range"
7
7
  input_html_options[:step] ||= 1
@@ -3,14 +3,15 @@ module SimpleForm
3
3
  class StringInput < Base
4
4
  enable :placeholder, :maxlength, :pattern
5
5
 
6
- def input
6
+ def input(wrapper_options = nil)
7
7
  unless string?
8
8
  input_html_classes.unshift("string")
9
9
  input_html_options[:type] ||= input_type if html5?
10
10
  end
11
11
 
12
- add_size!
13
- @builder.text_field(attribute_name, input_html_options)
12
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
13
+
14
+ @builder.text_field(attribute_name, merged_input_options)
14
15
  end
15
16
 
16
17
  private
@@ -3,8 +3,10 @@ module SimpleForm
3
3
  class TextInput < Base
4
4
  enable :placeholder, :maxlength
5
5
 
6
- def input
7
- @builder.text_area(attribute_name, input_html_options)
6
+ def input(wrapper_options = nil)
7
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
8
+
9
+ @builder.text_area(attribute_name, merged_input_options)
8
10
  end
9
11
  end
10
12
  end
@@ -0,0 +1,14 @@
1
+ require 'rails/railtie'
2
+
3
+ module SimpleForm
4
+ class Railtie < Rails::Railtie
5
+ config.eager_load_namespaces << SimpleForm
6
+
7
+ config.after_initialize do
8
+ unless SimpleForm.configured?
9
+ warn '[Simple Form] Simple Form is not configured in the application and will use the default values.' +
10
+ ' Use `rails generate simple_form:install` to generate the Simple Form configuration.'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,68 @@
1
+ module SimpleForm
2
+ module Tags
3
+ module CollectionExtensions
4
+ private
5
+
6
+ def render_collection
7
+ item_wrapper_tag = @options.fetch(:item_wrapper_tag, :span)
8
+ item_wrapper_class = @options[:item_wrapper_class]
9
+
10
+ @collection.map do |item|
11
+ value = value_for_collection(item, @value_method)
12
+ text = value_for_collection(item, @text_method)
13
+ default_html_options = default_html_options_for_collection(item, value)
14
+ additional_html_options = option_html_attributes(item)
15
+
16
+ rendered_item = yield item, value, text, default_html_options.merge(additional_html_options)
17
+
18
+ if @options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
19
+ label_options = default_html_options.slice(:index, :namespace)
20
+ label_options['class'] = @options[:item_label_class]
21
+ rendered_item = @template_object.label(@object_name, sanitize_attribute_name(value), rendered_item, label_options)
22
+ end
23
+
24
+ item_wrapper_tag ? @template_object.content_tag(item_wrapper_tag, rendered_item, class: item_wrapper_class) : rendered_item
25
+ end.join.html_safe
26
+ end
27
+
28
+ def wrap_rendered_collection(collection)
29
+ wrapper_tag = @options[:collection_wrapper_tag]
30
+
31
+ if wrapper_tag
32
+ wrapper_class = @options[:collection_wrapper_class]
33
+ @template_object.content_tag(wrapper_tag, collection, class: wrapper_class)
34
+ else
35
+ collection
36
+ end
37
+ end
38
+ end
39
+
40
+ class CollectionRadioButtons < ActionView::Helpers::Tags::CollectionRadioButtons
41
+ include CollectionExtensions
42
+
43
+ def render
44
+ wrap_rendered_collection(super)
45
+ end
46
+
47
+ private
48
+
49
+ def render_component(builder)
50
+ builder.radio_button + builder.label(class: "collection_radio_buttons")
51
+ end
52
+ end
53
+
54
+ class CollectionCheckBoxes < ActionView::Helpers::Tags::CollectionCheckBoxes
55
+ include CollectionExtensions
56
+
57
+ def render
58
+ wrap_rendered_collection(super)
59
+ end
60
+
61
+ private
62
+
63
+ def render_component(builder)
64
+ builder.check_box + builder.label(class: "collection_check_boxes")
65
+ end
66
+ end
67
+ end
68
+ end