simple_form 2.1.3 → 3.0.0.beta1

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.

Potentially problematic release.


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

Files changed (72) hide show
  1. data/CHANGELOG.md +6 -54
  2. data/README.md +129 -111
  3. data/lib/generators/simple_form/install_generator.rb +4 -4
  4. data/lib/generators/simple_form/templates/README +2 -2
  5. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +8 -11
  6. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +16 -16
  7. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +3 -3
  8. data/lib/simple_form.rb +31 -47
  9. data/lib/simple_form/action_view_extensions/builder.rb +0 -319
  10. data/lib/simple_form/action_view_extensions/builder.rb.orig +247 -0
  11. data/lib/simple_form/action_view_extensions/form_helper.rb +1 -1
  12. data/lib/simple_form/components.rb +1 -1
  13. data/lib/simple_form/components/errors.rb +1 -7
  14. data/lib/simple_form/components/hints.rb +2 -7
  15. data/lib/simple_form/components/html5.rb +1 -1
  16. data/lib/simple_form/components/labels.rb +4 -4
  17. data/lib/simple_form/components/maxlength.rb +1 -8
  18. data/lib/simple_form/error_notification.rb +2 -2
  19. data/lib/simple_form/form_builder.rb +144 -46
  20. data/lib/simple_form/form_builder.rb.orig +486 -0
  21. data/lib/simple_form/helpers.rb +1 -1
  22. data/lib/simple_form/inputs/base.rb +3 -10
  23. data/lib/simple_form/inputs/block_input.rb +1 -1
  24. data/lib/simple_form/inputs/boolean_input.rb +6 -6
  25. data/lib/simple_form/inputs/collection_input.rb +7 -7
  26. data/lib/simple_form/inputs/numeric_input.rb +0 -6
  27. data/lib/simple_form/inputs/password_input.rb +0 -1
  28. data/lib/simple_form/inputs/string_input.rb +0 -1
  29. data/lib/simple_form/railtie.rb +7 -0
  30. data/lib/simple_form/tags.rb +61 -0
  31. data/lib/simple_form/version.rb +1 -1
  32. data/lib/simple_form/version.rb.orig +7 -0
  33. data/lib/simple_form/wrappers.rb +1 -1
  34. data/lib/simple_form/wrappers/builder.rb +5 -29
  35. data/lib/simple_form/wrappers/many.rb +1 -1
  36. data/lib/simple_form/wrappers/root.rb +1 -1
  37. data/test/action_view_extensions/builder_test.rb +67 -87
  38. data/test/action_view_extensions/form_helper_test.rb +16 -16
  39. data/test/components/label_test.rb +46 -46
  40. data/test/form_builder/association_test.rb +23 -23
  41. data/test/form_builder/button_test.rb +4 -4
  42. data/test/form_builder/error_notification_test.rb +8 -8
  43. data/test/form_builder/error_test.rb +18 -65
  44. data/test/form_builder/general_test.rb +45 -65
  45. data/test/form_builder/hint_test.rb +23 -29
  46. data/test/form_builder/input_field_test.rb +12 -12
  47. data/test/form_builder/label_test.rb +6 -16
  48. data/test/form_builder/wrapper_test.rb +21 -21
  49. data/test/inputs/boolean_input_test.rb +23 -35
  50. data/test/inputs/collection_check_boxes_input_test.rb +55 -55
  51. data/test/inputs/collection_radio_buttons_input_test.rb +70 -79
  52. data/test/inputs/collection_select_input_test.rb +45 -51
  53. data/test/inputs/datetime_input_test.rb +11 -11
  54. data/test/inputs/disabled_test.rb +10 -10
  55. data/test/inputs/discovery_test.rb +4 -4
  56. data/test/inputs/file_input_test.rb +1 -1
  57. data/test/inputs/general_test.rb +12 -12
  58. data/test/inputs/grouped_collection_select_input_test.rb +20 -20
  59. data/test/inputs/hidden_input_test.rb +1 -1
  60. data/test/inputs/numeric_input_test.rb +3 -3
  61. data/test/inputs/priority_input_test.rb +3 -3
  62. data/test/inputs/readonly_test.rb +12 -12
  63. data/test/inputs/required_test.rb +5 -5
  64. data/test/inputs/string_input_test.rb +10 -25
  65. data/test/inputs/text_input_test.rb +1 -1
  66. data/test/support/misc_helpers.rb +24 -24
  67. data/test/support/mock_controller.rb +6 -6
  68. data/test/support/models.rb +37 -46
  69. data/test/test_helper.rb +20 -20
  70. metadata +49 -24
  71. checksums.yaml +0 -7
  72. data/lib/simple_form/core_ext/hash.rb +0 -16
@@ -0,0 +1,247 @@
1
+ module SimpleForm
2
+ module ActionViewExtensions
3
+ # A collection of methods required by simple_form but added to rails default form.
4
+ # This means that you can use such methods outside simple_form context.
5
+ module Builder
6
+
7
+ # Wrapper for using SimpleForm inside a default rails form.
8
+ # Example:
9
+ #
10
+ # form_for @user do |f|
11
+ # f.simple_fields_for :posts do |posts_form|
12
+ # # Here you have all simple_form methods available
13
+ # posts_form.input :title
14
+ # end
15
+ # end
16
+ def simple_fields_for(*args, &block)
17
+ options = args.extract_options!
18
+ options[:wrapper] = self.options[:wrapper] if options[:wrapper].nil?
19
+ options[:defaults] ||= self.options[:defaults]
20
+
21
+ if self.class < ActionView::Helpers::FormBuilder
22
+ options[:builder] ||= self.class
23
+ else
24
+ options[:builder] ||= SimpleForm::FormBuilder
25
+ end
26
+ fields_for(*(args << options), &block)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ module SimpleForm
33
+ module Tags
34
+ module CollectionExtensions
35
+ private
36
+
37
+ def render_collection
38
+ item_wrapper_tag = @options.fetch(:item_wrapper_tag, :span)
39
+ item_wrapper_class = @options[:item_wrapper_class]
40
+
41
+ @collection.map do |item|
42
+ value = value_for_collection(item, @value_method)
43
+ text = value_for_collection(item, @text_method)
44
+ default_html_options = default_html_options_for_collection(item, value)
45
+
46
+ rendered_item = yield item, value, text, default_html_options
47
+
48
+ item_wrapper_tag ? @template_object.content_tag(item_wrapper_tag, rendered_item, :class => item_wrapper_class) : rendered_item
49
+ end.join.html_safe
50
+ end
51
+
52
+ def wrap_rendered_collection(collection)
53
+ wrapper_tag = @options[:collection_wrapper_tag]
54
+
55
+ if wrapper_tag
56
+ wrapper_class = @options[:collection_wrapper_class]
57
+ @template_object.content_tag(wrapper_tag, collection, :class => wrapper_class)
58
+ else
59
+ collection
60
+ end
61
+ end
62
+ end
63
+
64
+ class CollectionRadioButtons < ActionView::Helpers::Tags::CollectionRadioButtons
65
+ include CollectionExtensions
66
+
67
+ def render
68
+ wrap_rendered_collection(super)
69
+ end
70
+
71
+ private
72
+
73
+ def render_component(builder)
74
+ builder.radio_button + builder.label(:class => "collection_radio_buttons")
75
+ end
76
+ end
77
+
78
+ class CollectionCheckBoxes < ActionView::Helpers::Tags::CollectionCheckBoxes
79
+ include CollectionExtensions
80
+
81
+ def render
82
+ wrap_rendered_collection(super)
83
+ end
84
+
85
+ private
86
+
87
+ def render_component(builder)
88
+ builder.check_box + builder.label(:class => "collection_check_boxes")
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ module ActionView::Helpers
95
+ class FormBuilder
96
+ include SimpleForm::ActionViewExtensions::Builder
97
+ end
98
+
99
+ <<<<<<< HEAD
100
+ # Create a collection of radio inputs for the attribute. Basically this
101
+ # helper will create a radio input associated with a label for each
102
+ # text/value option in the collection, using value_method and text_method
103
+ # to convert these text/value. You can give a symbol or a proc to both
104
+ # value_method and text_method, that will be evaluated for each item in
105
+ # the collection.
106
+ #
107
+ # == Examples
108
+ #
109
+ # form_for @user do |f|
110
+ # f.collection_radio_buttons :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
111
+ # end
112
+ #
113
+ # <input id="user_options_true" name="user[options]" type="radio" value="true" />
114
+ # <label class="collection_radio_buttons" for="user_options_true">Yes</label>
115
+ # <input id="user_options_false" name="user[options]" type="radio" value="false" />
116
+ # <label class="collection_radio_buttons" for="user_options_false">No</label>
117
+ #
118
+ # It is also possible to give a block that should generate the radio +
119
+ # label. To wrap the radio with the label, for instance:
120
+ #
121
+ # form_for @user do |f|
122
+ # f.collection_radio_buttons(
123
+ # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
124
+ # ) do |b|
125
+ # b.label { b.radio_button + b.text }
126
+ # end
127
+ # end
128
+ #
129
+ # == Options
130
+ #
131
+ # Collection radio accepts some extra options:
132
+ #
133
+ # * checked => the value that should be checked initially.
134
+ #
135
+ # * disabled => the value or values that should be disabled. Accepts a single
136
+ # item or an array of items.
137
+ #
138
+ # * collection_wrapper_tag => the tag to wrap the entire collection.
139
+ #
140
+ # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag
141
+ #
142
+ # * item_wrapper_tag => the tag to wrap each item in the collection.
143
+ #
144
+ # * item_wrapper_class => the CSS class to use for item_wrapper_tag
145
+ #
146
+ # * a block => to generate the label + radio or any other component.
147
+ def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
148
+ SimpleForm::Tags::CollectionRadioButtons.new(@object_name, method, @template, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options)).render(&block)
149
+ =======
150
+ module FormOptionsHelper
151
+ # Override Rails options_from_collection_for_select to handle lambdas/procs in
152
+ # text and value methods, so it works the same way as collection_radio_buttons
153
+ # and collection_check_boxes in SimpleForm. If none of text/value methods is a
154
+ # callable object, then it just delegates back to original collection select.
155
+ # FIXME: remove when support only Rails 4.0 forward
156
+ # https://github.com/rails/rails/commit/9035324367526af0300477a58b6d3efc15d1a5a8
157
+ alias :original_options_from_collection_for_select :options_from_collection_for_select
158
+ def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
159
+ if value_method.respond_to?(:call) || text_method.respond_to?(:call)
160
+ collection = collection.map do |item|
161
+ value = value_for_collection(item, value_method)
162
+ text = value_for_collection(item, text_method)
163
+
164
+ [value, text]
165
+ end
166
+
167
+ value_method, text_method = :first, :last
168
+ selected = extract_selected_and_disabled_and_call_procs selected, collection
169
+ end
170
+
171
+ original_options_from_collection_for_select collection, value_method, text_method, selected
172
+ end
173
+
174
+ private
175
+
176
+ def extract_selected_and_disabled_and_call_procs(selected, collection)
177
+ selected, disabled = extract_selected_and_disabled selected
178
+ selected_disabled = { :selected => selected, :disabled => disabled }
179
+
180
+ selected_disabled.each do |key, check|
181
+ if check.is_a? Proc
182
+ values = collection.map { |option| option.first if check.call(option.first) }
183
+ selected_disabled[key] = values
184
+ end
185
+ end
186
+ end
187
+
188
+ def value_for_collection(item, value) #:nodoc:
189
+ value.respond_to?(:call) ? value.call(item) : item.send(value)
190
+ >>>>>>> master
191
+ end
192
+
193
+ # Creates a collection of check boxes for each item in the collection,
194
+ # associated with a clickable label. Use value_method and text_method to
195
+ # convert items in the collection for use as text/value in check boxes.
196
+ # You can give a symbol or a proc to both value_method and text_method,
197
+ # that will be evaluated for each item in the collection.
198
+ #
199
+ # == Examples
200
+ #
201
+ # form_for @user do |f|
202
+ # f.collection_check_boxes :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
203
+ # end
204
+ #
205
+ # <input name="user[options][]" type="hidden" value="" />
206
+ # <input id="user_options_true" name="user[options][]" type="checkbox" value="true" />
207
+ # <label class="collection_check_boxes" for="user_options_true">Yes</label>
208
+ # <input name="user[options][]" type="hidden" value="" />
209
+ # <input id="user_options_false" name="user[options][]" type="checkbox" value="false" />
210
+ # <label class="collection_check_boxes" for="user_options_false">No</label>
211
+ #
212
+ # It is also possible to give a block that should generate the check box +
213
+ # label. To wrap the check box with the label, for instance:
214
+ #
215
+ # form_for @user do |f|
216
+ # f.collection_check_boxes(
217
+ # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
218
+ # ) do |b|
219
+ # b.label { b.check_box + b.text }
220
+ # end
221
+ # end
222
+ #
223
+ # == Options
224
+ #
225
+ # Collection check box accepts some extra options:
226
+ #
227
+ # * checked => the value or values that should be checked initially. Accepts
228
+ # a single item or an array of items. It overrides existing associations.
229
+ #
230
+ # * disabled => the value or values that should be disabled. Accepts a single
231
+ # item or an array of items.
232
+ #
233
+ # * collection_wrapper_tag => the tag to wrap the entire collection.
234
+ #
235
+ # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag. This option
236
+ # is ignored if the :collection_wrapper_tag option is blank.
237
+ #
238
+ # * item_wrapper_tag => the tag to wrap each item in the collection.
239
+ #
240
+ # * item_wrapper_class => the CSS class to use for item_wrapper_tag
241
+ #
242
+ # * a block => to generate the label + check box or any other component.
243
+ def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
244
+ SimpleForm::Tags::CollectionCheckBoxes.new(@object_name, method, @template, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options)).render(&block)
245
+ end
246
+ end
247
+ end
@@ -5,7 +5,7 @@ module SimpleForm
5
5
  # Example:
6
6
  #
7
7
  # simple_form_for @user do |f|
8
- # f.input :name, :hint => 'My hint'
8
+ # f.input :name, hint: 'My hint'
9
9
  # end
10
10
  #
11
11
  module FormHelper
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  # Components are a special type of helpers that can work on their own.
3
3
  # For example, by using a component, it will automatically change the
4
4
  # output under given circumstances without user input. For example,
5
- # the disabled helper always need a :disabled => true option given
5
+ # the disabled helper always need a disabled: true option given
6
6
  # to the input in order to be enabled. On the other hand, things like
7
7
  # hints can generate output automatically by doing I18n lookups.
8
8
  module Components
@@ -12,9 +12,7 @@ module SimpleForm
12
12
  protected
13
13
 
14
14
  def error_text
15
- text = has_error_in_options? ? options[:error] : errors.send(error_method)
16
-
17
- "#{html_escape(options[:error_prefix])} #{html_escape(text)}".lstrip.html_safe
15
+ "#{options[:error_prefix]} #{errors.send(error_method)}".lstrip.html_safe
18
16
  end
19
17
 
20
18
  def error_method
@@ -32,10 +30,6 @@ module SimpleForm
32
30
  def errors_on_association
33
31
  reflection ? object.errors[reflection.name] : []
34
32
  end
35
-
36
- def has_error_in_options?
37
- options[:error] && !options[:error].nil?
38
- end
39
33
  end
40
34
  end
41
35
  end
@@ -5,13 +5,8 @@ module SimpleForm
5
5
  def hint
6
6
  @hint ||= begin
7
7
  hint = options[:hint]
8
-
9
- if hint.is_a?(String)
10
- html_escape(hint)
11
- else
12
- content = translate(:hints)
13
- content.html_safe if content
14
- end
8
+ hint_content = hint.is_a?(String) ? hint : translate(:hints)
9
+ hint_content.html_safe if hint_content
15
10
  end
16
11
  end
17
12
 
@@ -23,4 +23,4 @@ module SimpleForm
23
23
  end
24
24
  end
25
25
  end
26
- end
26
+ end
@@ -6,18 +6,18 @@ module SimpleForm
6
6
  module ClassMethods #:nodoc:
7
7
  def translate_required_html
8
8
  i18n_cache :translate_required_html do
9
- I18n.t(:"simple_form.required.html", :default =>
9
+ I18n.t(:"simple_form.required.html", default:
10
10
  %[<abbr title="#{translate_required_text}">#{translate_required_mark}</abbr>]
11
11
  )
12
12
  end
13
13
  end
14
14
 
15
15
  def translate_required_text
16
- I18n.t(:"simple_form.required.text", :default => 'required')
16
+ I18n.t(:"simple_form.required.text", default: 'required')
17
17
  end
18
18
 
19
19
  def translate_required_mark
20
- I18n.t(:"simple_form.required.mark", :default => '*')
20
+ I18n.t(:"simple_form.required.mark", default: '*')
21
21
  end
22
22
  end
23
23
 
@@ -30,7 +30,7 @@ module SimpleForm
30
30
  end
31
31
 
32
32
  def label_text
33
- SimpleForm.label_text.call(html_escape(raw_label_text), required_label_text).strip.html_safe
33
+ SimpleForm.label_text.call(raw_label_text, required_label_text).strip.html_safe
34
34
  end
35
35
 
36
36
  def label_target
@@ -27,14 +27,7 @@ module SimpleForm
27
27
  end
28
28
 
29
29
  def has_tokenizer?(length_validator)
30
- tokenizer = length_validator.options[:tokenizer]
31
-
32
- # TODO: Remove this check when we drop Rails 3.0 support
33
- if ActiveModel::Validations::LengthValidator.const_defined?(:DEFAULT_TOKENIZER)
34
- tokenizer && tokenizer != ActiveModel::Validations::LengthValidator::DEFAULT_TOKENIZER
35
- else
36
- tokenizer
37
- end
30
+ length_validator.options[:tokenizer]
38
31
  end
39
32
  end
40
33
  end
@@ -1,6 +1,6 @@
1
1
  module SimpleForm
2
2
  class ErrorNotification
3
- delegate :object, :object_name, :template, :to => :@builder
3
+ delegate :object, :object_name, :template, to: :@builder
4
4
 
5
5
  def initialize(builder, options)
6
6
  @builder = builder
@@ -42,7 +42,7 @@ module SimpleForm
42
42
  lookups << :"#{object_name}"
43
43
  lookups << :default_message
44
44
  lookups << "Please review the problems below:"
45
- I18n.t(lookups.shift, :scope => :"simple_form.error_notification", :default => lookups)
45
+ I18n.t(lookups.shift, scope: :"simple_form.error_notification", default: lookups)
46
46
  end
47
47
  end
48
48
  end
@@ -1,5 +1,6 @@
1
- require 'simple_form/core_ext/hash'
1
+ require 'active_support/core_ext/object/deep_dup'
2
2
  require 'simple_form/map_type'
3
+ require 'simple_form/tags'
3
4
 
4
5
  module SimpleForm
5
6
  class FormBuilder < ActionView::Helpers::FormBuilder
@@ -7,26 +8,26 @@ module SimpleForm
7
8
 
8
9
  # When action is create or update, we still should use new and edit
9
10
  ACTIONS = {
10
- :create => :new,
11
- :update => :edit
11
+ create: :new,
12
+ update: :edit
12
13
  }
13
14
 
14
15
  extend MapType
15
16
  include SimpleForm::Inputs
16
17
 
17
- map_type :text, :to => SimpleForm::Inputs::TextInput
18
- map_type :file, :to => SimpleForm::Inputs::FileInput
19
- map_type :string, :email, :search, :tel, :url, :to => SimpleForm::Inputs::StringInput
20
- map_type :password, :to => SimpleForm::Inputs::PasswordInput
21
- map_type :integer, :decimal, :float, :to => SimpleForm::Inputs::NumericInput
22
- map_type :range, :to => SimpleForm::Inputs::RangeInput
23
- map_type :check_boxes, :to => SimpleForm::Inputs::CollectionCheckBoxesInput
24
- map_type :radio_buttons, :to => SimpleForm::Inputs::CollectionRadioButtonsInput
25
- map_type :select, :to => SimpleForm::Inputs::CollectionSelectInput
26
- map_type :grouped_select, :to => SimpleForm::Inputs::GroupedCollectionSelectInput
27
- map_type :date, :time, :datetime, :to => SimpleForm::Inputs::DateTimeInput
28
- map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput
29
- map_type :boolean, :to => SimpleForm::Inputs::BooleanInput
18
+ map_type :text, to: SimpleForm::Inputs::TextInput
19
+ map_type :file, to: SimpleForm::Inputs::FileInput
20
+ map_type :string, :email, :search, :tel, :url, to: SimpleForm::Inputs::StringInput
21
+ map_type :password, to: SimpleForm::Inputs::PasswordInput
22
+ map_type :integer, :decimal, :float, to: SimpleForm::Inputs::NumericInput
23
+ map_type :range, to: SimpleForm::Inputs::RangeInput
24
+ map_type :check_boxes, to: SimpleForm::Inputs::CollectionCheckBoxesInput
25
+ map_type :radio_buttons, to: SimpleForm::Inputs::CollectionRadioButtonsInput
26
+ map_type :select, to: SimpleForm::Inputs::CollectionSelectInput
27
+ map_type :grouped_select, to: SimpleForm::Inputs::GroupedCollectionSelectInput
28
+ map_type :date, :time, :datetime, to: SimpleForm::Inputs::DateTimeInput
29
+ map_type :country, :time_zone, to: SimpleForm::Inputs::PriorityInput
30
+ map_type :boolean, to: SimpleForm::Inputs::BooleanInput
30
31
 
31
32
  def self.discovery_cache
32
33
  @discovery_cache ||= {}
@@ -48,7 +49,7 @@ module SimpleForm
48
49
  #
49
50
  # # Imagine @user has error "can't be blank" on name
50
51
  # simple_form_for @user do |f|
51
- # f.input :name, :hint => 'My hint'
52
+ # f.input :name, hint: 'My hint'
52
53
  # end
53
54
  #
54
55
  # This is the output html (only the input portion, not the form):
@@ -57,7 +58,7 @@ module SimpleForm
57
58
  # <abbr title="required">*</abbr> Super User Name!
58
59
  # </label>
59
60
  # <input class="string required" id="user_name" maxlength="100"
60
- # name="user[name]" size="100" type="text" value="Carlos" />
61
+ # name="user[name]" type="text" value="Carlos" />
61
62
  # <span class="hint">My hint</span>
62
63
  # <span class="error">can't be blank</span>
63
64
  #
@@ -66,15 +67,15 @@ module SimpleForm
66
67
  #
67
68
  # You have some options for the input to enable/disable some functions:
68
69
  #
69
- # :as => allows you to define the input type you want, for instance you
70
+ # as: allows you to define the input type you want, for instance you
70
71
  # can use it to generate a text field for a date column.
71
72
  #
72
- # :required => defines whether this attribute is required or not. True
73
+ # required: defines whether this attribute is required or not. True
73
74
  # by default.
74
75
  #
75
76
  # The fact SimpleForm is built in components allow the interface to be unified.
76
77
  # So, for instance, if you need to disable :hint for a given input, you can pass
77
- # :hint => false. The same works for :error, :label and :wrapper.
78
+ # hint: false. The same works for :error, :label and :wrapper.
78
79
  #
79
80
  # Besides the html for any component can be changed. So, if you want to change
80
81
  # the label html you just need to give a hash to :label_html. To configure the
@@ -85,18 +86,18 @@ module SimpleForm
85
86
  # Some inputs, as datetime, time and select allow you to give extra options, like
86
87
  # prompt and/or include blank. Such options are given in plainly:
87
88
  #
88
- # f.input :created_at, :include_blank => true
89
+ # f.input :created_at, include_blank: true
89
90
  #
90
91
  # == Collection
91
92
  #
92
93
  # When playing with collections (:radio_buttons, :check_boxes and :select
93
94
  # inputs), you have three extra options:
94
95
  #
95
- # :collection => use to determine the collection to generate the radio or select
96
+ # collection: use to determine the collection to generate the radio or select
96
97
  #
97
- # :label_method => the method to apply on the array collection to get the label
98
+ # label_method: the method to apply on the array collection to get the label
98
99
  #
99
- # :value_method => the method to apply on the array collection to get the value
100
+ # value_method: the method to apply on the array collection to get the value
100
101
  #
101
102
  # == Priority
102
103
  #
@@ -130,14 +131,14 @@ module SimpleForm
130
131
  # This is the output html (only the input portion, not the form):
131
132
  #
132
133
  # <input class="string required" id="user_name" maxlength="100"
133
- # name="user[name]" size="100" type="text" value="Carlos" />
134
+ # name="user[name]" type="text" value="Carlos" />
134
135
  #
135
136
  def input_field(attribute_name, options={})
136
137
  options = options.dup
137
138
  options[:input_html] = options.except(:as, :collection, :label_method, :value_method)
138
139
  options = @defaults.deep_dup.deep_merge(options) if @defaults
139
140
 
140
- SimpleForm::Wrappers::Root.new([:min_max, :maxlength, :placeholder, :pattern, :readonly, :input], :wrapper => false).render find_input(attribute_name, options)
141
+ SimpleForm::Wrappers::Root.new([:min_max, :maxlength, :placeholder, :pattern, :readonly, :input], wrapper: false).render find_input(attribute_name, options)
141
142
  end
142
143
 
143
144
  # Helper for dealing with association selects/radios, generating the
@@ -151,7 +152,7 @@ module SimpleForm
151
152
  # f.association :company # Company.all
152
153
  # end
153
154
  #
154
- # f.association :company, :collection => Company.all(:order => 'name')
155
+ # f.association :company, collection: Company.all(order: 'name')
155
156
  # # Same as using :order option, but overriding collection
156
157
  #
157
158
  # == Block
@@ -190,7 +191,6 @@ module SimpleForm
190
191
  else
191
192
  if options[:as] == :select
192
193
  html_options = options[:input_html] ||= {}
193
- html_options[:size] ||= 5
194
194
  html_options[:multiple] = true unless html_options.key?(:multiple)
195
195
  end
196
196
 
@@ -203,7 +203,7 @@ module SimpleForm
203
203
  :"#{reflection.name.to_s.singularize}_ids"
204
204
  end
205
205
 
206
- input(attribute, options.merge(:reflection => reflection))
206
+ input(attribute, options.merge(reflection: reflection))
207
207
  end
208
208
 
209
209
  # Creates a button:
@@ -216,8 +216,7 @@ module SimpleForm
216
216
  # button implementation (3.2 forward (to delegate to the original when
217
217
  # calling `f.button :button`.
218
218
  #
219
- # TODO: remove if condition when supporting only Rails 3.2 forward.
220
- alias_method :button_button, :button if method_defined?(:button)
219
+ alias_method :button_button, :button
221
220
  def button(type, *args, &block)
222
221
  options = args.extract_options!.dup
223
222
  options[:class] = [SimpleForm.button_class, options[:class]].compact
@@ -235,7 +234,7 @@ module SimpleForm
235
234
  # == Examples
236
235
  #
237
236
  # f.error :name
238
- # f.error :name, :id => "cool_error"
237
+ # f.error :name, id: "cool_error"
239
238
  #
240
239
  def error(attribute_name, options={})
241
240
  options = options.dup
@@ -273,7 +272,7 @@ module SimpleForm
273
272
  # == Examples
274
273
  #
275
274
  # f.hint :name # Do I18n lookup
276
- # f.hint :name, :id => "cool_hint"
275
+ # f.hint :name, id: "cool_hint"
277
276
  # f.hint "Don't forget to accept this"
278
277
  #
279
278
  def hint(attribute_name, options={})
@@ -300,10 +299,10 @@ module SimpleForm
300
299
  #
301
300
  # f.label :name # Do I18n lookup
302
301
  # f.label :name, "Name" # Same behavior as Rails, do not add required tag
303
- # f.label :name, :label => "Name" # Same as above, but adds required tag
302
+ # f.label :name, label: "Name" # Same as above, but adds required tag
304
303
  #
305
- # f.label :name, :required => false
306
- # f.label :name, :id => "cool_label"
304
+ # f.label :name, required: false
305
+ # f.label :name, id: "cool_label"
307
306
  #
308
307
  def label(attribute_name, *args)
309
308
  return super if args.first.is_a?(String) || block_given?
@@ -324,13 +323,118 @@ module SimpleForm
324
323
  # == Examples
325
324
  #
326
325
  # f.error_notification
327
- # f.error_notification :message => 'Something went wrong'
328
- # f.error_notification :id => 'user_error_message', :class => 'form_error'
326
+ # f.error_notification message: 'Something went wrong'
327
+ # f.error_notification id: 'user_error_message', class: 'form_error'
329
328
  #
330
329
  def error_notification(options={})
331
330
  SimpleForm::ErrorNotification.new(self, options).render
332
331
  end
333
332
 
333
+ # Create a collection of radio inputs for the attribute. Basically this
334
+ # helper will create a radio input associated with a label for each
335
+ # text/value option in the collection, using value_method and text_method
336
+ # to convert these text/value. You can give a symbol or a proc to both
337
+ # value_method and text_method, that will be evaluated for each item in
338
+ # the collection.
339
+ #
340
+ # == Examples
341
+ #
342
+ # form_for @user do |f|
343
+ # f.collection_radio_buttons :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
344
+ # end
345
+ #
346
+ # <input id="user_options_true" name="user[options]" type="radio" value="true" />
347
+ # <label class="collection_radio_buttons" for="user_options_true">Yes</label>
348
+ # <input id="user_options_false" name="user[options]" type="radio" value="false" />
349
+ # <label class="collection_radio_buttons" for="user_options_false">No</label>
350
+ #
351
+ # It is also possible to give a block that should generate the radio +
352
+ # label. To wrap the radio with the label, for instance:
353
+ #
354
+ # form_for @user do |f|
355
+ # f.collection_radio_buttons(
356
+ # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
357
+ # ) do |b|
358
+ # b.label { b.radio_button + b.text }
359
+ # end
360
+ # end
361
+ #
362
+ # == Options
363
+ #
364
+ # Collection radio accepts some extra options:
365
+ #
366
+ # * checked => the value that should be checked initially.
367
+ #
368
+ # * disabled => the value or values that should be disabled. Accepts a single
369
+ # item or an array of items.
370
+ #
371
+ # * collection_wrapper_tag => the tag to wrap the entire collection.
372
+ #
373
+ # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag
374
+ #
375
+ # * item_wrapper_tag => the tag to wrap each item in the collection.
376
+ #
377
+ # * item_wrapper_class => the CSS class to use for item_wrapper_tag
378
+ #
379
+ # * a block => to generate the label + radio or any other component.
380
+ def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
381
+ SimpleForm::Tags::CollectionRadioButtons.new(@object_name, method, @template, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options)).render(&block)
382
+ end
383
+
384
+ # Creates a collection of check boxes for each item in the collection,
385
+ # associated with a clickable label. Use value_method and text_method to
386
+ # convert items in the collection for use as text/value in check boxes.
387
+ # You can give a symbol or a proc to both value_method and text_method,
388
+ # that will be evaluated for each item in the collection.
389
+ #
390
+ # == Examples
391
+ #
392
+ # form_for @user do |f|
393
+ # f.collection_check_boxes :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
394
+ # end
395
+ #
396
+ # <input name="user[options][]" type="hidden" value="" />
397
+ # <input id="user_options_true" name="user[options][]" type="checkbox" value="true" />
398
+ # <label class="collection_check_boxes" for="user_options_true">Yes</label>
399
+ # <input name="user[options][]" type="hidden" value="" />
400
+ # <input id="user_options_false" name="user[options][]" type="checkbox" value="false" />
401
+ # <label class="collection_check_boxes" for="user_options_false">No</label>
402
+ #
403
+ # It is also possible to give a block that should generate the check box +
404
+ # label. To wrap the check box with the label, for instance:
405
+ #
406
+ # form_for @user do |f|
407
+ # f.collection_check_boxes(
408
+ # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
409
+ # ) do |b|
410
+ # b.label { b.check_box + b.text }
411
+ # end
412
+ # end
413
+ #
414
+ # == Options
415
+ #
416
+ # Collection check box accepts some extra options:
417
+ #
418
+ # * checked => the value or values that should be checked initially. Accepts
419
+ # a single item or an array of items. It overrides existing associations.
420
+ #
421
+ # * disabled => the value or values that should be disabled. Accepts a single
422
+ # item or an array of items.
423
+ #
424
+ # * collection_wrapper_tag => the tag to wrap the entire collection.
425
+ #
426
+ # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag. This option
427
+ # is ignored if the :collection_wrapper_tag option is blank.
428
+ #
429
+ # * item_wrapper_tag => the tag to wrap each item in the collection.
430
+ #
431
+ # * item_wrapper_class => the CSS class to use for item_wrapper_tag
432
+ #
433
+ # * a block => to generate the label + check box or any other component.
434
+ def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
435
+ SimpleForm::Tags::CollectionCheckBoxes.new(@object_name, method, @template, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options)).render(&block)
436
+ end
437
+
334
438
  # Extract the model names from the object_name mess, ignoring numeric and
335
439
  # explicit child indexes.
336
440
  #
@@ -342,7 +446,7 @@ module SimpleForm
342
446
  def lookup_model_names
343
447
  @lookup_model_names ||= begin
344
448
  child_index = options[:child_index]
345
- names = object_name.to_s.scan(/(?!\d)\w+/).flatten
449
+ names = object_name.to_s.scan(/([a-zA-Z_]+)/).flatten
346
450
  names.delete(child_index) if child_index
347
451
  names.each { |name| name.gsub!('_attributes', '') }
348
452
  names.freeze
@@ -366,12 +470,6 @@ module SimpleForm
366
470
  column = find_attribute_column(attribute_name)
367
471
  input_type = default_input_type(attribute_name, column, options)
368
472
 
369
- if input_type == :radio
370
- SimpleForm.deprecation_warn "Using `:as => :radio` as input type is " \
371
- "deprecated, please change it to `:as => :radio_buttons`."
372
- input_type = :radio_buttons
373
- end
374
-
375
473
  if block_given?
376
474
  SimpleForm::Inputs::BlockInput.new(self, attribute_name, column, input_type, options, &block)
377
475
  else