simple_form 2.1.0 → 3.0.0.rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +15 -32
- data/README.md +103 -71
- data/lib/generators/simple_form/install_generator.rb +3 -3
- data/lib/generators/simple_form/templates/README +1 -1
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +13 -13
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +14 -14
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +3 -3
- data/lib/simple_form/action_view_extensions/builder.rb +1 -319
- data/lib/simple_form/action_view_extensions/form_helper.rb +2 -9
- data/lib/simple_form/components/html5.rb +5 -2
- data/lib/simple_form/components/labels.rb +3 -3
- data/lib/simple_form/components/maxlength.rb +1 -8
- data/lib/simple_form/components/pattern.rb +2 -2
- data/lib/simple_form/components.rb +1 -1
- data/lib/simple_form/error_notification.rb +2 -2
- data/lib/simple_form/form_builder.rb +147 -49
- data/lib/simple_form/helpers.rb +1 -1
- data/lib/simple_form/inputs/base.rb +2 -6
- data/lib/simple_form/inputs/block_input.rb +1 -1
- data/lib/simple_form/inputs/boolean_input.rb +5 -4
- data/lib/simple_form/inputs/collection_input.rb +6 -6
- data/lib/simple_form/inputs/numeric_input.rb +0 -6
- data/lib/simple_form/inputs/password_input.rb +0 -1
- data/lib/simple_form/inputs/string_input.rb +0 -1
- data/lib/simple_form/railtie.rb +7 -0
- data/lib/simple_form/tags.rb +61 -0
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/wrappers/builder.rb +5 -29
- data/lib/simple_form/wrappers/many.rb +1 -1
- data/lib/simple_form/wrappers/root.rb +1 -1
- data/lib/simple_form/wrappers.rb +1 -1
- data/lib/simple_form.rb +39 -47
- data/test/action_view_extensions/builder_test.rb +75 -88
- data/test/action_view_extensions/form_helper_test.rb +25 -16
- data/test/components/label_test.rb +46 -46
- data/test/form_builder/association_test.rb +39 -29
- data/test/form_builder/button_test.rb +4 -4
- data/test/form_builder/error_notification_test.rb +8 -8
- data/test/form_builder/error_test.rb +12 -12
- data/test/form_builder/general_test.rb +58 -52
- data/test/form_builder/hint_test.rb +22 -22
- data/test/form_builder/input_field_test.rb +12 -12
- data/test/form_builder/label_test.rb +6 -6
- data/test/form_builder/wrapper_test.rb +21 -21
- data/test/inputs/boolean_input_test.rb +23 -23
- data/test/inputs/collection_check_boxes_input_test.rb +61 -55
- data/test/inputs/collection_radio_buttons_input_test.rb +76 -79
- data/test/inputs/collection_select_input_test.rb +70 -45
- data/test/inputs/datetime_input_test.rb +17 -11
- data/test/inputs/disabled_test.rb +10 -10
- data/test/inputs/discovery_test.rb +4 -4
- data/test/inputs/file_input_test.rb +1 -1
- data/test/inputs/general_test.rb +12 -12
- data/test/inputs/grouped_collection_select_input_test.rb +20 -20
- data/test/inputs/hidden_input_test.rb +3 -2
- data/test/inputs/numeric_input_test.rb +3 -3
- data/test/inputs/priority_input_test.rb +9 -3
- data/test/inputs/readonly_test.rb +12 -12
- data/test/inputs/required_test.rb +5 -5
- data/test/inputs/string_input_test.rb +15 -25
- data/test/inputs/text_input_test.rb +1 -1
- data/test/support/misc_helpers.rb +46 -24
- data/test/support/mock_controller.rb +6 -6
- data/test/support/models.rb +62 -61
- data/test/test_helper.rb +20 -24
- metadata +32 -33
- data/lib/simple_form/action_view_extensions/builder.rb.orig +0 -247
- data/lib/simple_form/core_ext/hash.rb +0 -16
- data/lib/simple_form/form_builder.rb.orig +0 -486
- data/lib/simple_form/version.rb.orig +0 -7
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
require '
|
|
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
|
-
:
|
|
11
|
-
:
|
|
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, :
|
|
18
|
-
map_type :file, :
|
|
19
|
-
map_type :string, :email, :search, :tel, :url, :
|
|
20
|
-
map_type :password, :
|
|
21
|
-
map_type :integer, :decimal, :float, :
|
|
22
|
-
map_type :range, :
|
|
23
|
-
map_type :check_boxes, :
|
|
24
|
-
map_type :radio_buttons, :
|
|
25
|
-
map_type :select, :
|
|
26
|
-
map_type :grouped_select, :
|
|
27
|
-
map_type :date, :time, :datetime, :
|
|
28
|
-
map_type :country, :time_zone, :
|
|
29
|
-
map_type :boolean, :
|
|
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, :
|
|
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]"
|
|
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
|
-
# :
|
|
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
|
-
# :
|
|
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
|
-
# :
|
|
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, :
|
|
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
|
-
# :
|
|
96
|
+
# collection: use to determine the collection to generate the radio or select
|
|
96
97
|
#
|
|
97
|
-
# :
|
|
98
|
+
# label_method: the method to apply on the array collection to get the label
|
|
98
99
|
#
|
|
99
|
-
# :
|
|
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]"
|
|
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], :
|
|
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, :
|
|
155
|
+
# f.association :company, collection: Company.all(order: 'name')
|
|
155
156
|
# # Same as using :order option, but overriding collection
|
|
156
157
|
#
|
|
157
158
|
# == Block
|
|
@@ -179,7 +180,7 @@ module SimpleForm
|
|
|
179
180
|
|
|
180
181
|
options[:as] ||= :select
|
|
181
182
|
options[:collection] ||= options.fetch(:collection) {
|
|
182
|
-
reflection.klass.
|
|
183
|
+
reflection.klass.where(reflection.options[:conditions]).order(reflection.options[:order]).to_a
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
attribute = case reflection.macro
|
|
@@ -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(:
|
|
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
|
-
|
|
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, :
|
|
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, :
|
|
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, :
|
|
302
|
+
# f.label :name, label: "Name" # Same as above, but adds required tag
|
|
304
303
|
#
|
|
305
|
-
# f.label :name, :
|
|
306
|
-
# f.label :name, :
|
|
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 :
|
|
328
|
-
# f.error_notification :
|
|
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
|
#
|
|
@@ -339,7 +443,7 @@ module SimpleForm
|
|
|
339
443
|
# route[blocks_attributes][0][blocks_learning_object_attributes][1][foo_attributes]
|
|
340
444
|
# ["route", "blocks", "blocks_learning_object", "foo"]
|
|
341
445
|
#
|
|
342
|
-
def lookup_model_names
|
|
446
|
+
def lookup_model_names #:nodoc:
|
|
343
447
|
@lookup_model_names ||= begin
|
|
344
448
|
child_index = options[:child_index]
|
|
345
449
|
names = object_name.to_s.scan(/([a-zA-Z_]+)/).flatten
|
|
@@ -350,9 +454,9 @@ module SimpleForm
|
|
|
350
454
|
end
|
|
351
455
|
|
|
352
456
|
# The action to be used in lookup.
|
|
353
|
-
def lookup_action
|
|
457
|
+
def lookup_action #:nodoc:
|
|
354
458
|
@lookup_action ||= begin
|
|
355
|
-
action = template.controller.action_name
|
|
459
|
+
action = template.controller && template.controller.action_name
|
|
356
460
|
return unless action
|
|
357
461
|
action = action.to_sym
|
|
358
462
|
ACTIONS[action] || action
|
|
@@ -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
|
data/lib/simple_form/helpers.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module SimpleForm
|
|
2
2
|
# Helpers are made of several helpers that cannot be turned on automatically.
|
|
3
3
|
# For instance, disabled cannot be turned on automatically, it requires the
|
|
4
|
-
# user to explicitly pass the option :
|
|
4
|
+
# user to explicitly pass the option disabled: true so it may work.
|
|
5
5
|
module Helpers
|
|
6
6
|
autoload :Autofocus, 'simple_form/helpers/autofocus'
|
|
7
7
|
autoload :Disabled, 'simple_form/helpers/disabled'
|
|
@@ -24,7 +24,7 @@ module SimpleForm
|
|
|
24
24
|
attr_reader :attribute_name, :column, :input_type, :reflection,
|
|
25
25
|
:options, :input_html_options, :input_html_classes, :html_classes
|
|
26
26
|
|
|
27
|
-
delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, :
|
|
27
|
+
delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, to: :@builder
|
|
28
28
|
|
|
29
29
|
class_attribute :default_options
|
|
30
30
|
self.default_options = {}
|
|
@@ -90,10 +90,6 @@ module SimpleForm
|
|
|
90
90
|
|
|
91
91
|
private
|
|
92
92
|
|
|
93
|
-
def add_size!
|
|
94
|
-
input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
|
|
95
|
-
end
|
|
96
|
-
|
|
97
93
|
def limit
|
|
98
94
|
if column
|
|
99
95
|
decimal_or_float? ? decimal_limit : column_limit
|
|
@@ -179,7 +175,7 @@ module SimpleForm
|
|
|
179
175
|
lookups << :"defaults.#{reflection_or_attribute_name}"
|
|
180
176
|
lookups << default
|
|
181
177
|
|
|
182
|
-
I18n.t(lookups.shift, :
|
|
178
|
+
I18n.t(lookups.shift, scope: :"simple_form.#{namespace}", default: lookups).presence
|
|
183
179
|
end
|
|
184
180
|
end
|
|
185
181
|
end
|
|
@@ -4,7 +4,7 @@ module SimpleForm
|
|
|
4
4
|
def input
|
|
5
5
|
if nested_boolean_style?
|
|
6
6
|
build_hidden_field_for_checkbox +
|
|
7
|
-
template.label_tag(nil, :
|
|
7
|
+
template.label_tag(nil, class: "checkbox") {
|
|
8
8
|
build_check_box_without_hidden_field + inline_label
|
|
9
9
|
}
|
|
10
10
|
else
|
|
@@ -49,9 +49,10 @@ module SimpleForm
|
|
|
49
49
|
# we need the hidden field to be *outside* the label (otherwise it
|
|
50
50
|
# generates invalid html - html5 only).
|
|
51
51
|
def build_hidden_field_for_checkbox
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
options = { value: unchecked_value, id: nil, disabled: input_html_options[:disabled] }
|
|
53
|
+
options[:name] = input_html_options[:name] if input_html_options.has_key?(:name)
|
|
54
|
+
|
|
55
|
+
@builder.hidden_field(attribute_name, options)
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
def inline_label
|
|
@@ -7,8 +7,8 @@ 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", :
|
|
11
|
-
[I18n.t(:"simple_form.no", :
|
|
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
|
|
|
@@ -66,14 +66,14 @@ module SimpleForm
|
|
|
66
66
|
collection_translated = translate_collection if collection_classes == [Symbol]
|
|
67
67
|
|
|
68
68
|
if collection_translated || collection_classes.include?(Array)
|
|
69
|
-
{ :
|
|
69
|
+
{ label: :first, value: :last }
|
|
70
70
|
elsif collection_includes_basic_objects?(collection_classes)
|
|
71
|
-
{ :
|
|
71
|
+
{ label: :to_s, value: :to_s }
|
|
72
72
|
else
|
|
73
73
|
sample = collection.first || collection.last
|
|
74
74
|
|
|
75
|
-
{ :
|
|
76
|
-
:
|
|
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
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
@@ -4,7 +4,6 @@ module SimpleForm
|
|
|
4
4
|
enable :placeholder, :min_max
|
|
5
5
|
|
|
6
6
|
def input
|
|
7
|
-
add_size!
|
|
8
7
|
input_html_classes.unshift("numeric")
|
|
9
8
|
if html5?
|
|
10
9
|
input_html_options[:type] ||= "number"
|
|
@@ -14,11 +13,6 @@ module SimpleForm
|
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
private
|
|
17
|
-
|
|
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
|
|
21
|
-
end
|
|
22
16
|
end
|
|
23
17
|
end
|
|
24
18
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
|
|
15
|
+
rendered_item = yield item, value, text, default_html_options
|
|
16
|
+
|
|
17
|
+
item_wrapper_tag ? @template_object.content_tag(item_wrapper_tag, rendered_item, class: item_wrapper_class) : rendered_item
|
|
18
|
+
end.join.html_safe
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def wrap_rendered_collection(collection)
|
|
22
|
+
wrapper_tag = @options[:collection_wrapper_tag]
|
|
23
|
+
|
|
24
|
+
if wrapper_tag
|
|
25
|
+
wrapper_class = @options[:collection_wrapper_class]
|
|
26
|
+
@template_object.content_tag(wrapper_tag, collection, class: wrapper_class)
|
|
27
|
+
else
|
|
28
|
+
collection
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class CollectionRadioButtons < ActionView::Helpers::Tags::CollectionRadioButtons
|
|
34
|
+
include CollectionExtensions
|
|
35
|
+
|
|
36
|
+
def render
|
|
37
|
+
wrap_rendered_collection(super)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def render_component(builder)
|
|
43
|
+
builder.radio_button + builder.label(class: "collection_radio_buttons")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class CollectionCheckBoxes < ActionView::Helpers::Tags::CollectionCheckBoxes
|
|
48
|
+
include CollectionExtensions
|
|
49
|
+
|
|
50
|
+
def render
|
|
51
|
+
wrap_rendered_collection(super)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def render_component(builder)
|
|
57
|
+
builder.check_box + builder.label(class: "collection_check_boxes")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/simple_form/version.rb
CHANGED
|
@@ -12,18 +12,18 @@ module SimpleForm
|
|
|
12
12
|
# b.optional :placeholder
|
|
13
13
|
#
|
|
14
14
|
# # Use a component with specific wrapper options
|
|
15
|
-
# b.use :error, :
|
|
15
|
+
# b.use :error, wrap_with: { tag: "span", class: "error" }
|
|
16
16
|
#
|
|
17
17
|
# # Use a set of components by wrapping them in a tag+class.
|
|
18
|
-
# b.wrapper :
|
|
18
|
+
# b.wrapper tag: "div", class: "another" do |ba|
|
|
19
19
|
# ba.use :label
|
|
20
20
|
# ba.use :input
|
|
21
21
|
# end
|
|
22
22
|
#
|
|
23
23
|
# # Use a set of components by wrapping them in a tag+class.
|
|
24
24
|
# # This wrapper is identified by :label_input, which means it can
|
|
25
|
-
# # be turned off on demand with `f.input :name, :
|
|
26
|
-
# b.wrapper :label_input, :
|
|
25
|
+
# # be turned off on demand with `f.input :name, label_input: false`
|
|
26
|
+
# b.wrapper :label_input, tag: "div", class: "another" do |ba|
|
|
27
27
|
# ba.use :label
|
|
28
28
|
# ba.use :input
|
|
29
29
|
# end
|
|
@@ -32,7 +32,7 @@ module SimpleForm
|
|
|
32
32
|
# The builder also accepts default options at the root level. This is usually
|
|
33
33
|
# used if you want a component to be disabled by default:
|
|
34
34
|
#
|
|
35
|
-
# config.wrappers :
|
|
35
|
+
# config.wrappers hint: false do |b|
|
|
36
36
|
# b.use :hint
|
|
37
37
|
# b.use :label_input
|
|
38
38
|
# end
|
|
@@ -46,18 +46,6 @@ module SimpleForm
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def use(name, options=nil, &block)
|
|
49
|
-
if block_given?
|
|
50
|
-
ActiveSupport::Deprecation.warn "Passing a block to use is deprecated. " \
|
|
51
|
-
"Please use wrapper instead of use."
|
|
52
|
-
return wrapper(name, options, &block)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
if options && options.keys != [:wrap_with]
|
|
56
|
-
ActiveSupport::Deprecation.warn "Passing :tag, :class and others to use is deprecated. " \
|
|
57
|
-
"Please invoke b.use #{name.inspect}, :wrap_with => #{options.inspect} instead."
|
|
58
|
-
options = { :wrap_with => options }
|
|
59
|
-
end
|
|
60
|
-
|
|
61
49
|
if options && wrapper = options[:wrap_with]
|
|
62
50
|
@components << Single.new(name, wrapper)
|
|
63
51
|
else
|
|
@@ -66,18 +54,6 @@ module SimpleForm
|
|
|
66
54
|
end
|
|
67
55
|
|
|
68
56
|
def optional(name, options=nil, &block)
|
|
69
|
-
if block_given?
|
|
70
|
-
ActiveSupport::Deprecation.warn "Passing a block to optional is deprecated. " \
|
|
71
|
-
"Please use wrapper instead of optional."
|
|
72
|
-
return wrapper(name, options, &block)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
if options && options.keys != [:wrap_with]
|
|
76
|
-
ActiveSupport::Deprecation.warn "Passing :tag, :class and others to optional is deprecated. " \
|
|
77
|
-
"Please invoke b.optional #{name.inspect}, :wrap_with => #{options.inspect} instead."
|
|
78
|
-
options = { :wrap_with => options }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
57
|
@options[name] = false
|
|
82
58
|
use(name, options, &block)
|
|
83
59
|
end
|
|
@@ -23,7 +23,7 @@ module SimpleForm
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
25
|
def html_classes(input, options)
|
|
26
|
-
css = options[:wrapper_class] ? Array
|
|
26
|
+
css = options[:wrapper_class] ? Array(options[:wrapper_class]) : @defaults[:class]
|
|
27
27
|
css += SimpleForm.additional_classes_for(:wrapper) do
|
|
28
28
|
input.additional_classes + [input.input_class]
|
|
29
29
|
end
|
data/lib/simple_form/wrappers.rb
CHANGED