simple_form 2.1.3 → 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 +4 -4
- data/CHANGELOG.md +13 -50
- data/README.md +140 -116
- data/lib/generators/simple_form/install_generator.rb +4 -4
- data/lib/generators/simple_form/templates/README +2 -2
- 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 +16 -16
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +3 -3
- data/lib/simple_form/action_view_extensions/builder.rb +1 -320
- data/lib/simple_form/action_view_extensions/form_helper.rb +2 -9
- data/lib/simple_form/components/errors.rb +1 -7
- data/lib/simple_form/components/hints.rb +2 -7
- data/lib/simple_form/components/html5.rb +5 -2
- data/lib/simple_form/components/labels.rb +4 -4
- 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 +148 -50
- data/lib/simple_form/helpers.rb +1 -1
- data/lib/simple_form/inputs/base.rb +3 -10
- data/lib/simple_form/inputs/block_input.rb +1 -1
- data/lib/simple_form/inputs/boolean_input.rb +6 -6
- data/lib/simple_form/inputs/collection_input.rb +7 -7
- 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 -95
- 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 +18 -65
- data/test/form_builder/general_test.rb +60 -74
- data/test/form_builder/hint_test.rb +23 -29
- data/test/form_builder/input_field_test.rb +12 -12
- data/test/form_builder/label_test.rb +6 -16
- data/test/form_builder/wrapper_test.rb +21 -21
- data/test/inputs/boolean_input_test.rb +23 -35
- 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 -51
- 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 -64
- data/test/test_helper.rb +20 -24
- metadata +37 -23
- data/lib/simple_form/core_ext/hash.rb +0 -16
|
@@ -13,8 +13,8 @@ module SimpleForm
|
|
|
13
13
|
pattern = options[:pattern]
|
|
14
14
|
if pattern.is_a?(String)
|
|
15
15
|
pattern
|
|
16
|
-
elsif pattern_validator = find_pattern_validator
|
|
17
|
-
evaluate_format_validator_option(
|
|
16
|
+
elsif (pattern_validator = find_pattern_validator) && (with = pattern_validator.options[:with])
|
|
17
|
+
evaluate_format_validator_option(with).source
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -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 :
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module SimpleForm
|
|
2
2
|
class ErrorNotification
|
|
3
|
-
delegate :object, :object_name, :template, :
|
|
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, :
|
|
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 '
|
|
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,10 +443,10 @@ 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
|
-
names = object_name.to_s.scan(/(
|
|
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
|
|
@@ -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'
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
require 'simple_form/i18n_cache'
|
|
2
|
-
require 'active_support/core_ext/string/output_safety'
|
|
3
2
|
|
|
4
3
|
module SimpleForm
|
|
5
4
|
module Inputs
|
|
6
5
|
class Base
|
|
7
|
-
include ERB::Util
|
|
8
|
-
|
|
9
6
|
extend I18nCache
|
|
10
7
|
|
|
11
8
|
include SimpleForm::Helpers::Autofocus
|
|
@@ -27,7 +24,7 @@ module SimpleForm
|
|
|
27
24
|
attr_reader :attribute_name, :column, :input_type, :reflection,
|
|
28
25
|
:options, :input_html_options, :input_html_classes, :html_classes
|
|
29
26
|
|
|
30
|
-
delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, :
|
|
27
|
+
delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, to: :@builder
|
|
31
28
|
|
|
32
29
|
class_attribute :default_options
|
|
33
30
|
self.default_options = {}
|
|
@@ -45,7 +42,7 @@ module SimpleForm
|
|
|
45
42
|
end
|
|
46
43
|
|
|
47
44
|
# Always enabled.
|
|
48
|
-
enable :hint
|
|
45
|
+
enable :hint
|
|
49
46
|
|
|
50
47
|
# Usually disabled, needs to be enabled explicitly passing true as option.
|
|
51
48
|
disable :maxlength, :placeholder, :pattern, :min_max
|
|
@@ -93,10 +90,6 @@ module SimpleForm
|
|
|
93
90
|
|
|
94
91
|
private
|
|
95
92
|
|
|
96
|
-
def add_size!
|
|
97
|
-
input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
|
|
98
|
-
end
|
|
99
|
-
|
|
100
93
|
def limit
|
|
101
94
|
if column
|
|
102
95
|
decimal_or_float? ? decimal_limit : column_limit
|
|
@@ -182,7 +175,7 @@ module SimpleForm
|
|
|
182
175
|
lookups << :"defaults.#{reflection_or_attribute_name}"
|
|
183
176
|
lookups << default
|
|
184
177
|
|
|
185
|
-
I18n.t(lookups.shift, :
|
|
178
|
+
I18n.t(lookups.shift, scope: :"simple_form.#{namespace}", default: lookups).presence
|
|
186
179
|
end
|
|
187
180
|
end
|
|
188
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
|
|
@@ -17,7 +17,6 @@ module SimpleForm
|
|
|
17
17
|
input
|
|
18
18
|
elsif nested_boolean_style?
|
|
19
19
|
html_options = label_html_options.dup
|
|
20
|
-
html_options[:class] ||= []
|
|
21
20
|
html_options[:class].push(:checkbox)
|
|
22
21
|
|
|
23
22
|
build_hidden_field_for_checkbox +
|
|
@@ -35,7 +34,7 @@ module SimpleForm
|
|
|
35
34
|
# reuse the method for nested boolean style, but with no unchecked value,
|
|
36
35
|
# which won't generate the hidden checkbox. This is the default functionality
|
|
37
36
|
# in Rails > 3.2.1, and is backported in SimpleForm AV helpers.
|
|
38
|
-
def build_check_box(unchecked_value = unchecked_value
|
|
37
|
+
def build_check_box(unchecked_value = unchecked_value)
|
|
39
38
|
@builder.check_box(attribute_name, input_html_options, checked_value, unchecked_value)
|
|
40
39
|
end
|
|
41
40
|
|
|
@@ -50,9 +49,10 @@ module SimpleForm
|
|
|
50
49
|
# we need the hidden field to be *outside* the label (otherwise it
|
|
51
50
|
# generates invalid html - html5 only).
|
|
52
51
|
def build_hidden_field_for_checkbox
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
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
|
|
|
@@ -33,7 +33,7 @@ module SimpleForm
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def has_required?
|
|
36
|
-
super && (input_options[:include_blank] ||
|
|
36
|
+
super && (input_options[:include_blank] || multiple?)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# Check if :include_blank must be included by default.
|
|
@@ -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