simple_form_with_client_validation 0.0.0

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.
Files changed (99) hide show
  1. data/CHANGELOG.md +6 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +783 -0
  4. data/lib/generators/simple_form_with_client_validation/USAGE +3 -0
  5. data/lib/generators/simple_form_with_client_validation/install_generator.rb +32 -0
  6. data/lib/generators/simple_form_with_client_validation/templates/README +12 -0
  7. data/lib/generators/simple_form_with_client_validation/templates/_form.html.erb +13 -0
  8. data/lib/generators/simple_form_with_client_validation/templates/_form.html.haml +10 -0
  9. data/lib/generators/simple_form_with_client_validation/templates/_form.html.slim +10 -0
  10. data/lib/generators/simple_form_with_client_validation/templates/config/initializers/simple_form.rb.tt +179 -0
  11. data/lib/generators/simple_form_with_client_validation/templates/config/locales/simple_form.en.yml +26 -0
  12. data/lib/simple_form_with_client_validation/action_view_extensions/builder.rb +331 -0
  13. data/lib/simple_form_with_client_validation/action_view_extensions/form_helper.rb +74 -0
  14. data/lib/simple_form_with_client_validation/components/errors.rb +35 -0
  15. data/lib/simple_form_with_client_validation/components/hints.rb +18 -0
  16. data/lib/simple_form_with_client_validation/components/html5.rb +26 -0
  17. data/lib/simple_form_with_client_validation/components/label_input.rb +15 -0
  18. data/lib/simple_form_with_client_validation/components/labels.rb +79 -0
  19. data/lib/simple_form_with_client_validation/components/maxlength.rb +41 -0
  20. data/lib/simple_form_with_client_validation/components/min_max.rb +50 -0
  21. data/lib/simple_form_with_client_validation/components/minlength.rb +41 -0
  22. data/lib/simple_form_with_client_validation/components/pattern.rb +34 -0
  23. data/lib/simple_form_with_client_validation/components/placeholders.rb +16 -0
  24. data/lib/simple_form_with_client_validation/components/readonly.rb +22 -0
  25. data/lib/simple_form_with_client_validation/components.rb +21 -0
  26. data/lib/simple_form_with_client_validation/core_ext/hash.rb +16 -0
  27. data/lib/simple_form_with_client_validation/error_notification.rb +48 -0
  28. data/lib/simple_form_with_client_validation/form_builder.rb +484 -0
  29. data/lib/simple_form_with_client_validation/helpers/autofocus.rb +11 -0
  30. data/lib/simple_form_with_client_validation/helpers/disabled.rb +15 -0
  31. data/lib/simple_form_with_client_validation/helpers/readonly.rb +15 -0
  32. data/lib/simple_form_with_client_validation/helpers/required.rb +35 -0
  33. data/lib/simple_form_with_client_validation/helpers/validators.rb +44 -0
  34. data/lib/simple_form_with_client_validation/helpers.rb +12 -0
  35. data/lib/simple_form_with_client_validation/i18n_cache.rb +22 -0
  36. data/lib/simple_form_with_client_validation/inputs/base.rb +162 -0
  37. data/lib/simple_form_with_client_validation/inputs/block_input.rb +14 -0
  38. data/lib/simple_form_with_client_validation/inputs/boolean_input.rb +64 -0
  39. data/lib/simple_form_with_client_validation/inputs/collection_check_boxes_input.rb +21 -0
  40. data/lib/simple_form_with_client_validation/inputs/collection_input.rb +101 -0
  41. data/lib/simple_form_with_client_validation/inputs/collection_radio_buttons_input.rb +63 -0
  42. data/lib/simple_form_with_client_validation/inputs/collection_select_input.rb +14 -0
  43. data/lib/simple_form_with_client_validation/inputs/date_time_input.rb +28 -0
  44. data/lib/simple_form_with_client_validation/inputs/file_input.rb +9 -0
  45. data/lib/simple_form_with_client_validation/inputs/grouped_collection_select_input.rb +41 -0
  46. data/lib/simple_form_with_client_validation/inputs/hidden_input.rb +17 -0
  47. data/lib/simple_form_with_client_validation/inputs/numeric_input.rb +24 -0
  48. data/lib/simple_form_with_client_validation/inputs/password_input.rb +12 -0
  49. data/lib/simple_form_with_client_validation/inputs/priority_input.rb +24 -0
  50. data/lib/simple_form_with_client_validation/inputs/range_input.rb +14 -0
  51. data/lib/simple_form_with_client_validation/inputs/string_input.rb +23 -0
  52. data/lib/simple_form_with_client_validation/inputs/text_input.rb +11 -0
  53. data/lib/simple_form_with_client_validation/inputs.rb +21 -0
  54. data/lib/simple_form_with_client_validation/map_type.rb +16 -0
  55. data/lib/simple_form_with_client_validation/version.rb +3 -0
  56. data/lib/simple_form_with_client_validation/wrappers/builder.rb +115 -0
  57. data/lib/simple_form_with_client_validation/wrappers/many.rb +78 -0
  58. data/lib/simple_form_with_client_validation/wrappers/root.rb +34 -0
  59. data/lib/simple_form_with_client_validation/wrappers/single.rb +18 -0
  60. data/lib/simple_form_with_client_validation/wrappers.rb +8 -0
  61. data/lib/simple_form_with_client_validation.rb +218 -0
  62. data/test/action_view_extensions/builder_test.rb +577 -0
  63. data/test/action_view_extensions/form_helper_test.rb +104 -0
  64. data/test/components/label_test.rb +310 -0
  65. data/test/form_builder/association_test.rb +177 -0
  66. data/test/form_builder/button_test.rb +47 -0
  67. data/test/form_builder/error_notification_test.rb +79 -0
  68. data/test/form_builder/error_test.rb +121 -0
  69. data/test/form_builder/general_test.rb +356 -0
  70. data/test/form_builder/hint_test.rb +139 -0
  71. data/test/form_builder/input_field_test.rb +63 -0
  72. data/test/form_builder/label_test.rb +71 -0
  73. data/test/form_builder/wrapper_test.rb +149 -0
  74. data/test/generators/simple_form_generator_test.rb +32 -0
  75. data/test/inputs/boolean_input_test.rb +108 -0
  76. data/test/inputs/collection_check_boxes_input_test.rb +224 -0
  77. data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
  78. data/test/inputs/collection_select_input_test.rb +241 -0
  79. data/test/inputs/datetime_input_test.rb +99 -0
  80. data/test/inputs/disabled_test.rb +38 -0
  81. data/test/inputs/discovery_test.rb +61 -0
  82. data/test/inputs/file_input_test.rb +16 -0
  83. data/test/inputs/general_test.rb +69 -0
  84. data/test/inputs/grouped_collection_select_input_test.rb +118 -0
  85. data/test/inputs/hidden_input_test.rb +30 -0
  86. data/test/inputs/numeric_input_test.rb +173 -0
  87. data/test/inputs/priority_input_test.rb +43 -0
  88. data/test/inputs/readonly_test.rb +61 -0
  89. data/test/inputs/required_test.rb +113 -0
  90. data/test/inputs/string_input_test.rb +140 -0
  91. data/test/inputs/text_input_test.rb +29 -0
  92. data/test/simple_form_test.rb +9 -0
  93. data/test/support/discovery_inputs.rb +21 -0
  94. data/test/support/misc_helpers.rb +102 -0
  95. data/test/support/mock_controller.rb +24 -0
  96. data/test/support/mock_response.rb +14 -0
  97. data/test/support/models.rb +210 -0
  98. data/test/test_helper.rb +95 -0
  99. metadata +227 -0
@@ -0,0 +1,11 @@
1
+ module SimpleFormWithClientValidation
2
+ module Helpers
3
+ module Autofocus
4
+ private
5
+
6
+ def has_autofocus?
7
+ options[:autofocus] == true
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module SimpleFormWithClientValidation
2
+ module Helpers
3
+ module Disabled
4
+ private
5
+
6
+ def has_disabled?
7
+ options[:disabled] == true
8
+ end
9
+
10
+ def disabled_class
11
+ :disabled if has_disabled?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module SimpleFormWithClientValidation
2
+ module Helpers
3
+ module Readonly
4
+ private
5
+
6
+ def readonly_class
7
+ :readonly if has_readonly?
8
+ end
9
+
10
+ def has_readonly?
11
+ options[:readonly] == true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ module SimpleFormWithClientValidation
2
+ module Helpers
3
+ module Required
4
+ private
5
+
6
+ def required_field?
7
+ @required
8
+ end
9
+
10
+ def calculate_required
11
+ if !options[:required].nil?
12
+ options[:required]
13
+ elsif has_validators?
14
+ required_by_validators?
15
+ else
16
+ required_by_default?
17
+ end
18
+ end
19
+
20
+ def required_by_validators?
21
+ (attribute_validators + reflection_validators).any? { |v| v.kind == :presence && valid_validator?(v) }
22
+ end
23
+
24
+ def required_by_default?
25
+ SimpleFormWithClientValidation.required_by_default
26
+ end
27
+
28
+ # Do not use has_required? because we want to add the class
29
+ # regardless of the required option.
30
+ def required_class
31
+ required_field? ? :required : :optional
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ module SimpleFormWithClientValidation
2
+ module Helpers
3
+ module Validators
4
+ def has_validators?
5
+ @has_validators ||= attribute_name && object.class.respond_to?(:validators_on)
6
+ end
7
+
8
+ private
9
+
10
+ def attribute_validators
11
+ object.class.validators_on(attribute_name)
12
+ end
13
+
14
+ def reflection_validators
15
+ reflection ? object.class.validators_on(reflection.name) : []
16
+ end
17
+
18
+ def valid_validator?(validator)
19
+ !conditional_validators?(validator) && action_validator_match?(validator)
20
+ end
21
+
22
+ def conditional_validators?(validator)
23
+ validator.options.include?(:if) || validator.options.include?(:unless)
24
+ end
25
+
26
+ def action_validator_match?(validator)
27
+ return true if !validator.options.include?(:on)
28
+
29
+ case validator.options[:on]
30
+ when :save
31
+ true
32
+ when :create
33
+ !object.persisted?
34
+ when :update
35
+ object.persisted?
36
+ end
37
+ end
38
+
39
+ def find_validator(validator)
40
+ attribute_validators.find { |v| validator === v } if has_validators?
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ module SimpleFormWithClientValidation
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.
5
+ module Helpers
6
+ autoload :Autofocus, 'simple_form_with_client_validation/helpers/autofocus'
7
+ autoload :Disabled, 'simple_form_with_client_validation/helpers/disabled'
8
+ autoload :Readonly, 'simple_form_with_client_validation/helpers/readonly'
9
+ autoload :Required, 'simple_form_with_client_validation/helpers/required'
10
+ autoload :Validators, 'simple_form_with_client_validation/helpers/validators'
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ module SimpleFormWithClientValidation
2
+ # A lot of configuration values are retrived from I18n,
3
+ # like boolean collection, required string. This module provides
4
+ # caching facility to speed up form construction.
5
+ module I18nCache
6
+ def i18n_cache(key)
7
+ get_i18n_cache(key)[I18n.locale] ||= yield.freeze
8
+ end
9
+
10
+ def get_i18n_cache(key)
11
+ if class_variable_defined?(:"@@#{key}")
12
+ class_variable_get(:"@@#{key}")
13
+ else
14
+ reset_i18n_cache(key)
15
+ end
16
+ end
17
+
18
+ def reset_i18n_cache(key)
19
+ class_variable_set(:"@@#{key}", {})
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,162 @@
1
+ module SimpleFormWithClientValidation
2
+ module Inputs
3
+ class Base
4
+ extend I18nCache
5
+
6
+ include SimpleFormWithClientValidation::Helpers::Autofocus
7
+ include SimpleFormWithClientValidation::Helpers::Disabled
8
+ include SimpleFormWithClientValidation::Helpers::Readonly
9
+ include SimpleFormWithClientValidation::Helpers::Required
10
+ include SimpleFormWithClientValidation::Helpers::Validators
11
+
12
+ include SimpleFormWithClientValidation::Components::Errors
13
+ include SimpleFormWithClientValidation::Components::Hints
14
+ include SimpleFormWithClientValidation::Components::HTML5
15
+ include SimpleFormWithClientValidation::Components::LabelInput
16
+ include SimpleFormWithClientValidation::Components::Maxlength
17
+ include SimpleFormWithClientValidation::Components::Minlength
18
+ include SimpleFormWithClientValidation::Components::MinMax
19
+ include SimpleFormWithClientValidation::Components::Pattern
20
+ include SimpleFormWithClientValidation::Components::Placeholders
21
+ include SimpleFormWithClientValidation::Components::Readonly
22
+
23
+ attr_reader :attribute_name, :column, :input_type, :reflection,
24
+ :options, :input_html_options, :input_html_classes, :html_classes
25
+
26
+ delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, :to => :@builder
27
+
28
+ class_attribute :default_options
29
+ self.default_options = {}
30
+
31
+ def self.enable(*keys)
32
+ options = self.default_options.dup
33
+ keys.each { |key| options.delete(key) }
34
+ self.default_options = options
35
+ end
36
+
37
+ def self.disable(*keys)
38
+ options = self.default_options.dup
39
+ keys.each { |key| options[key] = false }
40
+ self.default_options = options
41
+ end
42
+
43
+ # Always enabled.
44
+ enable :hint
45
+
46
+ # Usually disabled, needs to be enabled explicitly passing true as option.
47
+ disable :maxlength, :placeholder, :pattern, :min_max
48
+
49
+ def initialize(builder, attribute_name, column, input_type, options = {})
50
+ super
51
+
52
+ @builder = builder
53
+ @attribute_name = attribute_name
54
+ @column = column
55
+ @input_type = input_type
56
+ @reflection = options.delete(:reflection)
57
+ @options = options.reverse_merge!(self.class.default_options)
58
+ @required = calculate_required
59
+
60
+ # Notice that html_options_for receives a reference to input_html_classes.
61
+ # This means that classes added dynamically to input_html_classes will
62
+ # still propagate to input_html_options.
63
+ @html_classes = SimpleFormWithClientValidation.additional_classes_for(:input) {
64
+ [input_type, required_class, readonly_class, disabled_class].compact
65
+ }
66
+
67
+ @input_html_classes = @html_classes.dup
68
+ @input_html_options = html_options_for(:input, input_html_classes).tap do |o|
69
+ o[:readonly] = true if has_readonly?
70
+ o[:disabled] = true if has_disabled?
71
+ o[:autofocus] = true if has_autofocus?
72
+ end
73
+ end
74
+
75
+ def input
76
+ raise NotImplementedError
77
+ end
78
+
79
+ def input_options
80
+ options
81
+ end
82
+
83
+ private
84
+
85
+ def add_size!
86
+ input_html_options[:size] ||= [limit, SimpleFormWithClientValidation.default_input_size].compact.min
87
+ end
88
+
89
+ def limit
90
+ column && column.limit
91
+ end
92
+
93
+ def nested_boolean_style?
94
+ options.fetch(:boolean_style, SimpleFormWithClientValidation.boolean_style) == :nested
95
+ end
96
+
97
+ # Find reflection name when available, otherwise use attribute
98
+ def reflection_or_attribute_name
99
+ reflection ? reflection.name : attribute_name
100
+ end
101
+
102
+ # Retrieve options for the given namespace from the options hash
103
+ def html_options_for(namespace, css_classes)
104
+ html_options = options[:"#{namespace}_html"] || {}
105
+ css_classes << html_options[:class] if html_options.key?(:class)
106
+ html_options[:class] = css_classes
107
+ html_options
108
+ end
109
+
110
+ # Lookup translations for the given namespace using I18n, based on object name,
111
+ # actual action and attribute name. Lookup priority as follows:
112
+ #
113
+ # simple_form.{namespace}.{model}.{action}.{attribute}
114
+ # simple_form.{namespace}.{model}.{attribute}
115
+ # simple_form.{namespace}.defaults.{attribute}
116
+ #
117
+ # Namespace is used for :labels and :hints.
118
+ #
119
+ # Model is the actual object name, for a @user object you'll have :user.
120
+ # Action is the action being rendered, usually :new or :edit.
121
+ # And attribute is the attribute itself, :name for example.
122
+ #
123
+ # The lookup for nested attributes is also done in a nested format using
124
+ # both model and nested object names, such as follow:
125
+ #
126
+ # simple_form.{namespace}.{model}.{nested}.{action}.{attribute}
127
+ # simple_form.{namespace}.{model}.{nested}.{attribute}
128
+ # simple_form.{namespace}.{nested}.{action}.{attribute}
129
+ # simple_form.{namespace}.{nested}.{attribute}
130
+ # simple_form.{namespace}.defaults.{attribute}
131
+ #
132
+ # Example:
133
+ #
134
+ # simple_form:
135
+ # labels:
136
+ # user:
137
+ # new:
138
+ # email: 'E-mail para efetuar o sign in.'
139
+ # edit:
140
+ # email: 'E-mail.'
141
+ #
142
+ # Take a look at our locale example file.
143
+ def translate(namespace, default='')
144
+ model_names = lookup_model_names.dup
145
+ lookups = []
146
+
147
+ while !model_names.empty?
148
+ joined_model_names = model_names.join(".")
149
+ model_names.shift
150
+
151
+ lookups << :"#{joined_model_names}.#{lookup_action}.#{reflection_or_attribute_name}"
152
+ lookups << :"#{joined_model_names}.#{reflection_or_attribute_name}"
153
+ end
154
+ lookups << :"defaults.#{lookup_action}.#{reflection_or_attribute_name}"
155
+ lookups << :"defaults.#{attribute_name}"
156
+ lookups << default
157
+
158
+ I18n.t(lookups.shift, :scope => :"simple_form.#{namespace}", :default => lookups).presence
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,14 @@
1
+ module SimpleFormWithClientValidation
2
+ module Inputs
3
+ class BlockInput < Base
4
+ def initialize(*args, &block)
5
+ super
6
+ @block = block
7
+ end
8
+
9
+ def input
10
+ template.capture(&@block)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,64 @@
1
+ module SimpleFormWithClientValidation
2
+ module Inputs
3
+ class BooleanInput < Base
4
+ def input
5
+ if nested_boolean_style?
6
+ build_hidden_field_for_checkbox +
7
+ template.label_tag(nil, :class => "checkbox") {
8
+ build_check_box_without_hidden_field + options[:inline_label]
9
+ }
10
+ else
11
+ build_check_box
12
+ end
13
+ end
14
+
15
+ def label_input
16
+ if options[:label] == false
17
+ input
18
+ elsif nested_boolean_style?
19
+ html_options = label_html_options.dup
20
+ html_options[:class].push(:checkbox)
21
+
22
+ build_hidden_field_for_checkbox +
23
+ @builder.label(label_target, html_options) {
24
+ build_check_box_without_hidden_field + label_text
25
+ }
26
+ else
27
+ input + label
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # Build a checkbox tag using default unchecked value. This allows us to
34
+ # reuse the method for nested boolean style, but with no unchecked value,
35
+ # which won't generate the hidden checkbox. This is the default functionality
36
+ # in Rails > 3.2.1, and is backported in SimpleFormWithClientValidation AV helpers.
37
+ def build_check_box(unchecked_value='0')
38
+ @builder.check_box(attribute_name, input_html_options, '1', unchecked_value)
39
+ end
40
+
41
+ # Build a checkbox without generating the hidden field. See
42
+ # #build_hidden_field_for_checkbox for more info.
43
+ def build_check_box_without_hidden_field
44
+ build_check_box(nil)
45
+ end
46
+
47
+ # Create a hidden field for the current checkbox, so we can simulate Rails
48
+ # functionality with hidden + checkbox, but under a nested context, where
49
+ # we need the hidden field to be *outside* the label (otherwise it
50
+ # generates invalid html - html5 only).
51
+ def build_hidden_field_for_checkbox
52
+ @builder.hidden_field(attribute_name, :value => '0', :id => nil,
53
+ :disabled => input_html_options[:disabled])
54
+ end
55
+
56
+ # Booleans are not required by default because in most of the cases
57
+ # it makes no sense marking them as required. The only exception is
58
+ # Terms of Use usually presented at most sites sign up screen.
59
+ def required_by_default?
60
+ false
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,21 @@
1
+ module SimpleFormWithClientValidation
2
+ module Inputs
3
+ class CollectionCheckBoxesInput < CollectionRadioButtonsInput
4
+ protected
5
+
6
+ # Checkbox components do not use the required html tag.
7
+ # More info: https://github.com/plataformatec/simple_form/issues/340#issuecomment-2871956
8
+ def has_required?
9
+ false
10
+ end
11
+
12
+ def build_nested_boolean_style_item_tag(collection_builder)
13
+ collection_builder.check_box + collection_builder.text
14
+ end
15
+
16
+ def item_wrapper_class
17
+ "checkbox"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,101 @@
1
+ module SimpleFormWithClientValidation
2
+ module Inputs
3
+ class CollectionInput < Base
4
+ # Default boolean collection for use with selects/radios when no
5
+ # collection is given. Always fallback to this boolean collection.
6
+ # Texts can be translated using i18n in "simple_form.yes" and
7
+ # "simple_form.no" keys. See the example locale file.
8
+ def self.boolean_collection
9
+ i18n_cache :boolean_collection do
10
+ [ [I18n.t(:"simple_form.yes", :default => 'Yes'), true],
11
+ [I18n.t(:"simple_form.no", :default => 'No'), false] ]
12
+ end
13
+ end
14
+
15
+ def input
16
+ raise NotImplementedError,
17
+ "input should be implemented by classes inheriting from CollectionInput"
18
+ end
19
+
20
+ def input_options
21
+ options = super
22
+ options[:include_blank] = true unless skip_include_blank?
23
+ options
24
+ end
25
+
26
+ private
27
+
28
+ def collection
29
+ @collection ||= begin
30
+ collection = options.delete(:collection) || self.class.boolean_collection
31
+ collection.respond_to?(:call) ? collection.call : collection.to_a
32
+ end
33
+ end
34
+
35
+ def has_required?
36
+ super && (input_options[:include_blank] || multiple?)
37
+ end
38
+
39
+ # Check if :include_blank must be included by default.
40
+ def skip_include_blank?
41
+ (options.keys & [:prompt, :include_blank, :default, :selected]).any? || multiple?
42
+ end
43
+
44
+ def multiple?
45
+ !!options[:input_html].try(:[], :multiple)
46
+ end
47
+
48
+ # Detect the right method to find the label and value for a collection.
49
+ # If no label or value method are defined, will attempt to find them based
50
+ # on default label and value methods that can be configured through
51
+ # SimpleFormWithClientValidation.collection_label_methods and
52
+ # SimpleFormWithClientValidation.collection_value_methods.
53
+ def detect_collection_methods
54
+ label, value = options.delete(:label_method), options.delete(:value_method)
55
+
56
+ unless label && value
57
+ common_method_for = detect_common_display_methods
58
+ label ||= common_method_for[:label]
59
+ value ||= common_method_for[:value]
60
+ end
61
+
62
+ [label, value]
63
+ end
64
+
65
+ def detect_common_display_methods(collection_classes = detect_collection_classes)
66
+ collection_translated = translate_collection if collection_classes == [Symbol]
67
+
68
+ if collection_translated || collection_classes.include?(Array)
69
+ { :label => :first, :value => :last }
70
+ elsif collection_includes_basic_objects?(collection_classes)
71
+ { :label => :to_s, :value => :to_s }
72
+ else
73
+ sample = collection.first || collection.last
74
+
75
+ { :label => SimpleFormWithClientValidation.collection_label_methods.find { |m| sample.respond_to?(m) },
76
+ :value => SimpleFormWithClientValidation.collection_value_methods.find { |m| sample.respond_to?(m) } }
77
+ end
78
+ end
79
+
80
+ def detect_collection_classes(some_collection = collection)
81
+ some_collection.map { |e| e.class }.uniq
82
+ end
83
+
84
+ def collection_includes_basic_objects?(collection_classes)
85
+ (collection_classes & [
86
+ String, Integer, Fixnum, Bignum, Float, NilClass, Symbol, TrueClass, FalseClass
87
+ ]).any?
88
+ end
89
+
90
+ def translate_collection
91
+ if translated_collection = translate(:options)
92
+ @collection = collection.map do |key|
93
+ [translated_collection[key] || key, key]
94
+ end
95
+ true
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+