simple_form 1.5.2 → 2.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.
- data/CHANGELOG.md +224 -0
- data/MIT-LICENSE +1 -1
- data/README.md +817 -0
- data/lib/generators/simple_form/install_generator.rb +15 -1
- data/lib/generators/simple_form/templates/README +12 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb.tt +173 -0
- data/lib/simple_form.rb +109 -43
- data/lib/simple_form/action_view_extensions/builder.rb +158 -53
- data/lib/simple_form/action_view_extensions/form_helper.rb +29 -22
- data/lib/simple_form/components.rb +11 -1
- data/lib/simple_form/components/errors.rb +6 -24
- data/lib/simple_form/components/hints.rb +7 -21
- data/lib/simple_form/components/html5.rb +26 -0
- data/lib/simple_form/components/labels.rb +15 -13
- data/lib/simple_form/components/maxlength.rb +41 -0
- data/lib/simple_form/components/min_max.rb +49 -0
- data/lib/simple_form/components/pattern.rb +34 -0
- data/lib/simple_form/components/placeholders.rb +5 -17
- data/lib/simple_form/components/readonly.rb +22 -0
- data/lib/simple_form/core_ext/hash.rb +16 -0
- data/lib/simple_form/error_notification.rb +8 -1
- data/lib/simple_form/form_builder.rb +86 -22
- data/lib/simple_form/helpers.rb +7 -4
- data/lib/simple_form/helpers/autofocus.rb +11 -0
- data/lib/simple_form/helpers/disabled.rb +15 -0
- data/lib/simple_form/helpers/readonly.rb +15 -0
- data/lib/simple_form/helpers/required.rb +7 -10
- data/lib/simple_form/helpers/validators.rb +4 -4
- data/lib/simple_form/inputs.rb +17 -13
- data/lib/simple_form/inputs/base.rb +50 -81
- data/lib/simple_form/inputs/boolean_input.rb +43 -4
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +21 -0
- data/lib/simple_form/inputs/collection_input.rb +27 -13
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +69 -0
- data/lib/simple_form/inputs/collection_select_input.rb +14 -0
- data/lib/simple_form/inputs/date_time_input.rb +2 -2
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +41 -0
- data/lib/simple_form/inputs/hidden_input.rb +3 -6
- data/lib/simple_form/inputs/numeric_input.rb +3 -51
- data/lib/simple_form/inputs/password_input.rb +1 -2
- data/lib/simple_form/inputs/priority_input.rb +2 -2
- data/lib/simple_form/inputs/range_input.rb +1 -3
- data/lib/simple_form/inputs/string_input.rb +6 -8
- data/lib/simple_form/inputs/text_input.rb +1 -2
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/wrappers.rb +8 -0
- data/lib/simple_form/wrappers/builder.rb +75 -0
- data/lib/simple_form/wrappers/many.rb +68 -0
- data/lib/simple_form/wrappers/root.rb +34 -0
- data/lib/simple_form/wrappers/single.rb +18 -0
- data/test/action_view_extensions/builder_test.rb +195 -100
- data/test/action_view_extensions/form_helper_test.rb +24 -2
- data/test/components/label_test.rb +20 -5
- data/test/form_builder/association_test.rb +167 -0
- data/test/form_builder/button_test.rb +28 -0
- data/test/{error_notification_test.rb → form_builder/error_notification_test.rb} +2 -1
- data/test/form_builder/error_test.rb +101 -0
- data/test/form_builder/general_test.rb +348 -0
- data/test/form_builder/hint_test.rb +115 -0
- data/test/form_builder/input_field_test.rb +51 -0
- data/test/form_builder/label_test.rb +51 -0
- data/test/form_builder/wrapper_test.rb +140 -0
- data/test/generators/simple_form_generator_test.rb +32 -0
- data/test/inputs/boolean_input_test.rb +91 -0
- data/test/inputs/collection_check_boxes_input_test.rb +224 -0
- data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
- data/test/inputs/collection_select_input_test.rb +241 -0
- data/test/inputs/datetime_input_test.rb +85 -0
- data/test/inputs/disabled_test.rb +38 -0
- data/test/inputs/discovery_test.rb +61 -0
- data/test/inputs/file_input_test.rb +16 -0
- data/test/inputs/general_test.rb +69 -0
- data/test/inputs/grouped_collection_select_input_test.rb +109 -0
- data/test/inputs/hidden_input_test.rb +30 -0
- data/test/inputs/numeric_input_test.rb +167 -0
- data/test/inputs/priority_input_test.rb +43 -0
- data/test/inputs/readonly_test.rb +61 -0
- data/test/inputs/required_test.rb +113 -0
- data/test/inputs/string_input_test.rb +140 -0
- data/test/inputs/text_input_test.rb +24 -0
- data/test/{discovery_inputs.rb → support/discovery_inputs.rb} +0 -0
- data/test/support/misc_helpers.rb +48 -6
- data/test/support/mock_controller.rb +2 -2
- data/test/support/models.rb +20 -5
- data/test/test_helper.rb +5 -8
- metadata +123 -98
- data/.gitignore +0 -3
- data/.gitmodules +0 -3
- data/.travis.yml +0 -15
- data/CHANGELOG.rdoc +0 -159
- data/Gemfile +0 -9
- data/README.rdoc +0 -466
- data/Rakefile +0 -27
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +0 -93
- data/lib/simple_form/components/wrapper.rb +0 -38
- data/lib/simple_form/helpers/has_errors.rb +0 -15
- data/lib/simple_form/helpers/maxlength.rb +0 -24
- data/lib/simple_form/helpers/pattern.rb +0 -28
- data/simple_form.gemspec +0 -25
- data/test/components/error_test.rb +0 -56
- data/test/components/hint_test.rb +0 -74
- data/test/components/wrapper_test.rb +0 -63
- data/test/custom_components.rb +0 -7
- data/test/form_builder_test.rb +0 -930
- data/test/inputs_test.rb +0 -995
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# TODO: Delete this file when we drop support for Rails 3.0
|
|
2
|
+
# This method is already implemented in active_support 3.1
|
|
3
|
+
|
|
4
|
+
unless Hash.new.respond_to?(:deep_dup)
|
|
5
|
+
class Hash
|
|
6
|
+
# Returns a deep copy of hash.
|
|
7
|
+
def deep_dup
|
|
8
|
+
duplicate = self.dup
|
|
9
|
+
duplicate.each_pair do |k,v|
|
|
10
|
+
tv = duplicate[k]
|
|
11
|
+
duplicate[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_dup : v
|
|
12
|
+
end
|
|
13
|
+
duplicate
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
module SimpleForm
|
|
2
2
|
class ErrorNotification
|
|
3
3
|
delegate :object, :object_name, :template, :to => :@builder
|
|
4
|
-
include SimpleForm::Helpers::HasErrors
|
|
5
4
|
|
|
6
5
|
def initialize(builder, options)
|
|
7
6
|
@builder = builder
|
|
@@ -17,6 +16,14 @@ module SimpleForm
|
|
|
17
16
|
|
|
18
17
|
protected
|
|
19
18
|
|
|
19
|
+
def errors
|
|
20
|
+
object.errors
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def has_errors?
|
|
24
|
+
object && object.respond_to?(:errors) && errors.present?
|
|
25
|
+
end
|
|
26
|
+
|
|
20
27
|
def error_message
|
|
21
28
|
@message || translate_error_notification
|
|
22
29
|
end
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
require 'simple_form/core_ext/hash'
|
|
2
|
+
|
|
1
3
|
module SimpleForm
|
|
2
4
|
class FormBuilder < ActionView::Helpers::FormBuilder
|
|
3
|
-
attr_reader :template, :object_name, :object
|
|
5
|
+
attr_reader :template, :object_name, :object, :wrapper
|
|
6
|
+
|
|
7
|
+
# When action is create or update, we still should use new and edit
|
|
8
|
+
ACTIONS = {
|
|
9
|
+
:create => :new,
|
|
10
|
+
:update => :edit
|
|
11
|
+
}
|
|
4
12
|
|
|
5
13
|
extend MapType
|
|
6
14
|
include SimpleForm::Inputs
|
|
@@ -11,7 +19,10 @@ module SimpleForm
|
|
|
11
19
|
map_type :password, :to => SimpleForm::Inputs::PasswordInput
|
|
12
20
|
map_type :integer, :decimal, :float, :to => SimpleForm::Inputs::NumericInput
|
|
13
21
|
map_type :range, :to => SimpleForm::Inputs::RangeInput
|
|
14
|
-
map_type :
|
|
22
|
+
map_type :check_boxes, :to => SimpleForm::Inputs::CollectionCheckBoxesInput
|
|
23
|
+
map_type :radio_buttons, :to => SimpleForm::Inputs::CollectionRadioButtonsInput
|
|
24
|
+
map_type :select, :to => SimpleForm::Inputs::CollectionSelectInput
|
|
25
|
+
map_type :grouped_select, :to => SimpleForm::Inputs::GroupedCollectionSelectInput
|
|
15
26
|
map_type :date, :time, :datetime, :to => SimpleForm::Inputs::DateTimeInput
|
|
16
27
|
map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput
|
|
17
28
|
map_type :boolean, :to => SimpleForm::Inputs::BooleanInput
|
|
@@ -20,6 +31,12 @@ module SimpleForm
|
|
|
20
31
|
@discovery_cache ||= {}
|
|
21
32
|
end
|
|
22
33
|
|
|
34
|
+
def initialize(*) #:nodoc:
|
|
35
|
+
super
|
|
36
|
+
@defaults = options[:defaults]
|
|
37
|
+
@wrapper = SimpleForm.wrapper(options[:wrapper] || SimpleForm.default_wrapper)
|
|
38
|
+
end
|
|
39
|
+
|
|
23
40
|
# Basic input helper, combines all components in the stack to generate
|
|
24
41
|
# input html based on options the user define and some guesses through
|
|
25
42
|
# database column information. By default a call to input will generate
|
|
@@ -71,8 +88,8 @@ module SimpleForm
|
|
|
71
88
|
#
|
|
72
89
|
# == Collection
|
|
73
90
|
#
|
|
74
|
-
# When playing with collections (:
|
|
75
|
-
# options:
|
|
91
|
+
# When playing with collections (:radio_buttons, :check_boxes and :select
|
|
92
|
+
# inputs), you have three extra options:
|
|
76
93
|
#
|
|
77
94
|
# :collection => use to determine the collection to generate the radio or select
|
|
78
95
|
#
|
|
@@ -86,14 +103,16 @@ module SimpleForm
|
|
|
86
103
|
# given SimpleForm.time_zone_priority and SimpleForm.country_priority are used respectivelly.
|
|
87
104
|
#
|
|
88
105
|
def input(attribute_name, options={}, &block)
|
|
89
|
-
|
|
90
|
-
input_type = default_input_type(attribute_name, column, options)
|
|
106
|
+
options = @defaults.deep_dup.deep_merge(options) if @defaults
|
|
91
107
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
108
|
+
chosen =
|
|
109
|
+
if name = options[:wrapper]
|
|
110
|
+
name.respond_to?(:render) ? name : SimpleForm.wrapper(name)
|
|
111
|
+
else
|
|
112
|
+
wrapper
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
chosen.render find_input(attribute_name, options, &block)
|
|
97
116
|
end
|
|
98
117
|
alias :attribute :input
|
|
99
118
|
|
|
@@ -112,12 +131,8 @@ module SimpleForm
|
|
|
112
131
|
# name="user[name]" size="100" type="text" value="Carlos" />
|
|
113
132
|
#
|
|
114
133
|
def input_field(attribute_name, options={})
|
|
115
|
-
column = find_attribute_column(attribute_name)
|
|
116
|
-
input_type = default_input_type(attribute_name, column, options)
|
|
117
|
-
|
|
118
134
|
options[:input_html] = options.except(:as, :collection, :label_method, :value_method)
|
|
119
|
-
|
|
120
|
-
find_mapping(input_type).new(self, attribute_name, column, input_type, options).input
|
|
135
|
+
SimpleForm::Wrappers::Root.new([:input], :wrapper => false).render find_input(attribute_name, options)
|
|
121
136
|
end
|
|
122
137
|
|
|
123
138
|
# Helper for dealing with association selects/radios, generating the
|
|
@@ -160,7 +175,7 @@ module SimpleForm
|
|
|
160
175
|
|
|
161
176
|
attribute = case reflection.macro
|
|
162
177
|
when :belongs_to
|
|
163
|
-
reflection.options[:foreign_key] || :"#{reflection.name}_id"
|
|
178
|
+
(reflection.respond_to?(:options) && reflection.options[:foreign_key]) || :"#{reflection.name}_id"
|
|
164
179
|
when :has_one
|
|
165
180
|
raise ":has_one associations are not supported by f.association"
|
|
166
181
|
else
|
|
@@ -192,7 +207,7 @@ module SimpleForm
|
|
|
192
207
|
#
|
|
193
208
|
def button(type, *args, &block)
|
|
194
209
|
options = args.extract_options!
|
|
195
|
-
options[:class] =
|
|
210
|
+
options[:class] = [SimpleForm.button_class, options[:class]].compact
|
|
196
211
|
args << options
|
|
197
212
|
if respond_to?("#{type}_button")
|
|
198
213
|
send("#{type}_button", *args, &block)
|
|
@@ -213,7 +228,8 @@ module SimpleForm
|
|
|
213
228
|
options[:error_html] = options.except(:error_tag, :error_prefix, :error_method)
|
|
214
229
|
column = find_attribute_column(attribute_name)
|
|
215
230
|
input_type = default_input_type(attribute_name, column, options)
|
|
216
|
-
|
|
231
|
+
wrapper.find(:error).
|
|
232
|
+
render(SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options))
|
|
217
233
|
end
|
|
218
234
|
|
|
219
235
|
# Return the error but also considering its name. This is used
|
|
@@ -244,7 +260,7 @@ module SimpleForm
|
|
|
244
260
|
# f.hint "Don't forget to accept this"
|
|
245
261
|
#
|
|
246
262
|
def hint(attribute_name, options={})
|
|
247
|
-
options[:hint_html] = options.except(:hint_tag)
|
|
263
|
+
options[:hint_html] = options.except(:hint_tag, :hint)
|
|
248
264
|
if attribute_name.is_a?(String)
|
|
249
265
|
options[:hint] = attribute_name
|
|
250
266
|
attribute_name, column, input_type = nil, nil, nil
|
|
@@ -252,7 +268,9 @@ module SimpleForm
|
|
|
252
268
|
column = find_attribute_column(attribute_name)
|
|
253
269
|
input_type = default_input_type(attribute_name, column, options)
|
|
254
270
|
end
|
|
255
|
-
|
|
271
|
+
|
|
272
|
+
wrapper.find(:hint).
|
|
273
|
+
render(SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options))
|
|
256
274
|
end
|
|
257
275
|
|
|
258
276
|
# Creates a default label tag for the given attribute. You can give a label
|
|
@@ -294,7 +312,53 @@ module SimpleForm
|
|
|
294
312
|
SimpleForm::ErrorNotification.new(self, options).render
|
|
295
313
|
end
|
|
296
314
|
|
|
297
|
-
|
|
315
|
+
# Extract the model names from the object_name mess, ignoring numeric and
|
|
316
|
+
# explicit child indexes.
|
|
317
|
+
#
|
|
318
|
+
# Example:
|
|
319
|
+
#
|
|
320
|
+
# route[blocks_attributes][0][blocks_learning_object_attributes][1][foo_attributes]
|
|
321
|
+
# ["route", "blocks", "blocks_learning_object", "foo"]
|
|
322
|
+
#
|
|
323
|
+
def lookup_model_names
|
|
324
|
+
@lookup_model_names ||= begin
|
|
325
|
+
child_index = options[:child_index]
|
|
326
|
+
names = object_name.to_s.scan(/([a-zA-Z_]+)/).flatten
|
|
327
|
+
names.delete(child_index) if child_index
|
|
328
|
+
names.each { |name| name.gsub!('_attributes', '') }
|
|
329
|
+
names.freeze
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# The action to be used in lookup.
|
|
334
|
+
def lookup_action
|
|
335
|
+
@lookup_action ||= begin
|
|
336
|
+
action = template.controller.action_name
|
|
337
|
+
return unless action
|
|
338
|
+
action = action.to_sym
|
|
339
|
+
ACTIONS[action] || action
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
private
|
|
344
|
+
|
|
345
|
+
# Find an input based on the attribute name.
|
|
346
|
+
def find_input(attribute_name, options={}, &block) #:nodoc:
|
|
347
|
+
column = find_attribute_column(attribute_name)
|
|
348
|
+
input_type = default_input_type(attribute_name, column, options)
|
|
349
|
+
|
|
350
|
+
if input_type == :radio
|
|
351
|
+
SimpleForm.deprecation_warn "Using `:as => :radio` as input type is " \
|
|
352
|
+
"deprecated, please change it to `:as => :radio_buttons`."
|
|
353
|
+
input_type = :radio_buttons
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
if block_given?
|
|
357
|
+
SimpleForm::Inputs::BlockInput.new(self, attribute_name, column, input_type, options, &block)
|
|
358
|
+
else
|
|
359
|
+
find_mapping(input_type).new(self, attribute_name, column, input_type, options)
|
|
360
|
+
end
|
|
361
|
+
end
|
|
298
362
|
|
|
299
363
|
# Attempt to guess the better input type given the defined options. By
|
|
300
364
|
# default alwayls fallback to the user :as option, or to a :select when a
|
data/lib/simple_form/helpers.rb
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
module SimpleForm
|
|
2
|
+
# Helpers are made of several helpers that cannot be turned on automatically.
|
|
3
|
+
# For instance, disabled cannot be turned on automatically, it requires the
|
|
4
|
+
# user to explicitly pass the option :disabled => true so it may work.
|
|
2
5
|
module Helpers
|
|
3
|
-
autoload :
|
|
4
|
-
autoload :
|
|
5
|
-
autoload :
|
|
6
|
-
autoload :Validators, 'simple_form/helpers/validators'
|
|
6
|
+
autoload :Autofocus, 'simple_form/helpers/autofocus'
|
|
7
|
+
autoload :Disabled, 'simple_form/helpers/disabled'
|
|
8
|
+
autoload :Readonly, 'simple_form/helpers/readonly'
|
|
7
9
|
autoload :Required, 'simple_form/helpers/required'
|
|
10
|
+
autoload :Validators, 'simple_form/helpers/validators'
|
|
8
11
|
end
|
|
9
12
|
end
|
|
@@ -3,7 +3,7 @@ module SimpleForm
|
|
|
3
3
|
module Required
|
|
4
4
|
private
|
|
5
5
|
|
|
6
|
-
def
|
|
6
|
+
def required_field?
|
|
7
7
|
@required
|
|
8
8
|
end
|
|
9
9
|
|
|
@@ -15,22 +15,19 @@ module SimpleForm
|
|
|
15
15
|
v.kind == :presence && valid_validator?(v)
|
|
16
16
|
end
|
|
17
17
|
else
|
|
18
|
-
|
|
18
|
+
required_by_default?
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
def has_required?
|
|
24
|
-
attribute_required? && SimpleForm.html5 && SimpleForm.browser_validations
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def attribute_required_by_default?
|
|
22
|
+
def required_by_default?
|
|
28
23
|
SimpleForm.required_by_default
|
|
29
24
|
end
|
|
30
25
|
|
|
26
|
+
# Do not use has_required? because we want to add the class
|
|
27
|
+
# regardless of the required option.
|
|
31
28
|
def required_class
|
|
32
|
-
|
|
29
|
+
required_field? ? :required : :optional
|
|
33
30
|
end
|
|
34
31
|
end
|
|
35
32
|
end
|
|
36
|
-
end
|
|
33
|
+
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module SimpleForm
|
|
2
2
|
module Helpers
|
|
3
3
|
module Validators
|
|
4
|
-
private
|
|
5
|
-
|
|
6
4
|
def has_validators?
|
|
7
|
-
attribute_name && object.class.respond_to?(:validators_on)
|
|
5
|
+
@has_validators ||= attribute_name && object.class.respond_to?(:validators_on)
|
|
8
6
|
end
|
|
9
7
|
|
|
8
|
+
private
|
|
9
|
+
|
|
10
10
|
def attribute_validators
|
|
11
11
|
object.class.validators_on(attribute_name)
|
|
12
12
|
end
|
|
@@ -37,7 +37,7 @@ module SimpleForm
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def find_validator(validator)
|
|
40
|
-
attribute_validators.find { |v| validator === v }
|
|
40
|
+
attribute_validators.find { |v| validator === v } if has_validators?
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
end
|
data/lib/simple_form/inputs.rb
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
module SimpleForm
|
|
2
2
|
module Inputs
|
|
3
|
-
autoload :Base,
|
|
4
|
-
autoload :BlockInput,
|
|
5
|
-
autoload :BooleanInput,
|
|
6
|
-
autoload :
|
|
7
|
-
autoload :
|
|
8
|
-
autoload :
|
|
9
|
-
autoload :
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :
|
|
12
|
-
autoload :
|
|
13
|
-
autoload :
|
|
14
|
-
autoload :
|
|
15
|
-
autoload :
|
|
3
|
+
autoload :Base, 'simple_form/inputs/base'
|
|
4
|
+
autoload :BlockInput, 'simple_form/inputs/block_input'
|
|
5
|
+
autoload :BooleanInput, 'simple_form/inputs/boolean_input'
|
|
6
|
+
autoload :CollectionCheckBoxesInput, 'simple_form/inputs/collection_check_boxes_input'
|
|
7
|
+
autoload :CollectionInput, 'simple_form/inputs/collection_input'
|
|
8
|
+
autoload :CollectionRadioButtonsInput, 'simple_form/inputs/collection_radio_buttons_input'
|
|
9
|
+
autoload :CollectionSelectInput, 'simple_form/inputs/collection_select_input'
|
|
10
|
+
autoload :DateTimeInput, 'simple_form/inputs/date_time_input'
|
|
11
|
+
autoload :FileInput, 'simple_form/inputs/file_input'
|
|
12
|
+
autoload :GroupedCollectionSelectInput, 'simple_form/inputs/grouped_collection_select_input'
|
|
13
|
+
autoload :HiddenInput, 'simple_form/inputs/hidden_input'
|
|
14
|
+
autoload :NumericInput, 'simple_form/inputs/numeric_input'
|
|
15
|
+
autoload :PasswordInput, 'simple_form/inputs/password_input'
|
|
16
|
+
autoload :PriorityInput, 'simple_form/inputs/priority_input'
|
|
17
|
+
autoload :RangeInput, 'simple_form/inputs/range_input'
|
|
18
|
+
autoload :StringInput, 'simple_form/inputs/string_input'
|
|
19
|
+
autoload :TextInput, 'simple_form/inputs/text_input'
|
|
16
20
|
end
|
|
17
21
|
end
|
|
@@ -3,49 +3,68 @@ module SimpleForm
|
|
|
3
3
|
class Base
|
|
4
4
|
extend I18nCache
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
:update => :edit
|
|
10
|
-
}
|
|
11
|
-
|
|
6
|
+
include SimpleForm::Helpers::Autofocus
|
|
7
|
+
include SimpleForm::Helpers::Disabled
|
|
8
|
+
include SimpleForm::Helpers::Readonly
|
|
12
9
|
include SimpleForm::Helpers::Required
|
|
13
10
|
include SimpleForm::Helpers::Validators
|
|
14
|
-
include SimpleForm::Helpers::Maxlength
|
|
15
|
-
include SimpleForm::Helpers::Pattern
|
|
16
11
|
|
|
17
12
|
include SimpleForm::Components::Errors
|
|
18
13
|
include SimpleForm::Components::Hints
|
|
14
|
+
include SimpleForm::Components::HTML5
|
|
19
15
|
include SimpleForm::Components::LabelInput
|
|
16
|
+
include SimpleForm::Components::Maxlength
|
|
17
|
+
include SimpleForm::Components::MinMax
|
|
18
|
+
include SimpleForm::Components::Pattern
|
|
20
19
|
include SimpleForm::Components::Placeholders
|
|
21
|
-
include SimpleForm::Components::
|
|
20
|
+
include SimpleForm::Components::Readonly
|
|
21
|
+
|
|
22
|
+
attr_reader :attribute_name, :column, :input_type, :reflection,
|
|
23
|
+
:options, :input_html_options, :input_html_classes, :html_classes
|
|
24
|
+
|
|
25
|
+
delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, :to => :@builder
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
class_attribute :default_options
|
|
28
|
+
self.default_options = {}
|
|
29
|
+
|
|
30
|
+
def self.enable(*keys)
|
|
31
|
+
options = self.default_options.dup
|
|
32
|
+
keys.each { |key| options.delete(key) }
|
|
33
|
+
self.default_options = options
|
|
26
34
|
end
|
|
27
35
|
|
|
28
|
-
def self.disable(*
|
|
29
|
-
|
|
36
|
+
def self.disable(*keys)
|
|
37
|
+
options = self.default_options.dup
|
|
38
|
+
keys.each { |key| options[key] = false }
|
|
39
|
+
self.default_options = options
|
|
30
40
|
end
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
# Always enabled.
|
|
43
|
+
enable :hint
|
|
34
44
|
|
|
35
|
-
|
|
45
|
+
# Usually disabled, needs to be enabled explicitly passing true as option.
|
|
46
|
+
disable :maxlength, :placeholder, :pattern, :min_max
|
|
36
47
|
|
|
37
48
|
def initialize(builder, attribute_name, column, input_type, options = {})
|
|
49
|
+
super
|
|
50
|
+
|
|
38
51
|
@builder = builder
|
|
39
52
|
@attribute_name = attribute_name
|
|
40
53
|
@column = column
|
|
41
54
|
@input_type = input_type
|
|
42
55
|
@reflection = options.delete(:reflection)
|
|
43
|
-
@options = options
|
|
56
|
+
@options = options.reverse_merge!(self.class.default_options)
|
|
44
57
|
@required = calculate_required
|
|
58
|
+
|
|
59
|
+
# Notice that html_options_for receives a reference to input_html_classes.
|
|
60
|
+
# This means that classes added dynamically to input_html_classes will
|
|
61
|
+
# still propagate to input_html_options.
|
|
62
|
+
@html_classes = [input_type, required_class, readonly_class, disabled_class].compact
|
|
63
|
+
@input_html_classes = @html_classes.dup
|
|
45
64
|
@input_html_options = html_options_for(:input, input_html_classes).tap do |o|
|
|
46
|
-
o[:
|
|
47
|
-
o[:disabled] = true if
|
|
48
|
-
o[:autofocus] = true if has_autofocus?
|
|
65
|
+
o[:readonly] = true if has_readonly?
|
|
66
|
+
o[:disabled] = true if has_disabled?
|
|
67
|
+
o[:autofocus] = true if has_autofocus?
|
|
49
68
|
end
|
|
50
69
|
end
|
|
51
70
|
|
|
@@ -57,20 +76,6 @@ module SimpleForm
|
|
|
57
76
|
options
|
|
58
77
|
end
|
|
59
78
|
|
|
60
|
-
def input_html_classes
|
|
61
|
-
[input_type, required_class]
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def render
|
|
65
|
-
content = "".html_safe
|
|
66
|
-
components_list.each do |component|
|
|
67
|
-
next if options[component] == false
|
|
68
|
-
rendered = send(component)
|
|
69
|
-
content.safe_concat rendered.to_s if rendered
|
|
70
|
-
end
|
|
71
|
-
wrap(content)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
79
|
private
|
|
75
80
|
|
|
76
81
|
def add_size!
|
|
@@ -81,17 +86,8 @@ module SimpleForm
|
|
|
81
86
|
column && column.limit
|
|
82
87
|
end
|
|
83
88
|
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
ActiveSupport::Deprecation.warn "The option :components of f.input is deprecated. Please turn off each component individually instead."
|
|
87
|
-
components
|
|
88
|
-
else
|
|
89
|
-
SimpleForm.components
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def has_autofocus?
|
|
94
|
-
options[:autofocus]
|
|
89
|
+
def nested_boolean_style?
|
|
90
|
+
options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
|
|
95
91
|
end
|
|
96
92
|
|
|
97
93
|
# Find reflection name when available, otherwise use attribute
|
|
@@ -100,22 +96,19 @@ module SimpleForm
|
|
|
100
96
|
end
|
|
101
97
|
|
|
102
98
|
# Retrieve options for the given namespace from the options hash
|
|
103
|
-
def html_options_for(namespace,
|
|
99
|
+
def html_options_for(namespace, css_classes)
|
|
104
100
|
html_options = options[:"#{namespace}_html"] || {}
|
|
105
|
-
|
|
101
|
+
css_classes << html_options[:class] if html_options.key?(:class)
|
|
102
|
+
html_options[:class] = css_classes
|
|
106
103
|
html_options
|
|
107
104
|
end
|
|
108
105
|
|
|
109
|
-
def disabled?
|
|
110
|
-
options[:disabled] == true
|
|
111
|
-
end
|
|
112
|
-
|
|
113
106
|
# Lookup translations for the given namespace using I18n, based on object name,
|
|
114
107
|
# actual action and attribute name. Lookup priority as follows:
|
|
115
108
|
#
|
|
116
109
|
# simple_form.{namespace}.{model}.{action}.{attribute}
|
|
117
110
|
# simple_form.{namespace}.{model}.{attribute}
|
|
118
|
-
# simple_form.{namespace}.{attribute}
|
|
111
|
+
# simple_form.{namespace}.defaults.{attribute}
|
|
119
112
|
#
|
|
120
113
|
# Namespace is used for :labels and :hints.
|
|
121
114
|
#
|
|
@@ -130,7 +123,7 @@ module SimpleForm
|
|
|
130
123
|
# simple_form.{namespace}.{model}.{nested}.{attribute}
|
|
131
124
|
# simple_form.{namespace}.{nested}.{action}.{attribute}
|
|
132
125
|
# simple_form.{namespace}.{nested}.{attribute}
|
|
133
|
-
# simple_form.{namespace}.{attribute}
|
|
126
|
+
# simple_form.{namespace}.defaults.{attribute}
|
|
134
127
|
#
|
|
135
128
|
# Example:
|
|
136
129
|
#
|
|
@@ -144,9 +137,7 @@ module SimpleForm
|
|
|
144
137
|
#
|
|
145
138
|
# Take a look at our locale example file.
|
|
146
139
|
def translate(namespace, default='')
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
model_names = lookup_model_names
|
|
140
|
+
model_names = lookup_model_names.dup
|
|
150
141
|
lookups = []
|
|
151
142
|
|
|
152
143
|
while !model_names.empty?
|
|
@@ -156,34 +147,12 @@ module SimpleForm
|
|
|
156
147
|
lookups << :"#{joined_model_names}.#{lookup_action}.#{reflection_or_attribute_name}"
|
|
157
148
|
lookups << :"#{joined_model_names}.#{reflection_or_attribute_name}"
|
|
158
149
|
end
|
|
159
|
-
lookups << :"
|
|
150
|
+
lookups << :"defaults.#{lookup_action}.#{reflection_or_attribute_name}"
|
|
151
|
+
lookups << :"defaults.#{attribute_name}"
|
|
160
152
|
lookups << default
|
|
161
153
|
|
|
162
154
|
I18n.t(lookups.shift, :scope => :"simple_form.#{namespace}", :default => lookups).presence
|
|
163
155
|
end
|
|
164
|
-
|
|
165
|
-
# Extract the model names from the object_name mess, ignoring numeric and
|
|
166
|
-
# explicit child indexes.
|
|
167
|
-
#
|
|
168
|
-
# Example:
|
|
169
|
-
#
|
|
170
|
-
# route[blocks_attributes][0][blocks_learning_object_attributes][1][foo_attributes]
|
|
171
|
-
# ["route", "blocks", "blocks_learning_object", "foo"]
|
|
172
|
-
#
|
|
173
|
-
def lookup_model_names
|
|
174
|
-
child_index = @builder.options[:child_index]
|
|
175
|
-
names = object_name.to_s.scan(/([a-zA-Z_]+)/).flatten
|
|
176
|
-
names.delete(child_index) if child_index
|
|
177
|
-
names.each { |name| name.gsub!('_attributes', '') }
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# The action to be used in lookup.
|
|
181
|
-
def lookup_action
|
|
182
|
-
action = template.controller.action_name
|
|
183
|
-
return unless action
|
|
184
|
-
action = action.to_sym
|
|
185
|
-
ACTIONS[action] || action
|
|
186
|
-
end
|
|
187
156
|
end
|
|
188
157
|
end
|
|
189
158
|
end
|