formtastic 3.1.3 → 5.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 (179) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test.yml +61 -0
  4. data/.gitignore +3 -2
  5. data/CHANGELOG.md +61 -0
  6. data/Gemfile.lock +140 -0
  7. data/MIT-LICENSE +1 -1
  8. data/{README.textile → README.md} +183 -167
  9. data/RELEASE_PROCESS +3 -1
  10. data/Rakefile +20 -1
  11. data/app/assets/stylesheets/formtastic.css +1 -1
  12. data/bin/appraisal +8 -0
  13. data/formtastic.gemspec +12 -16
  14. data/gemfiles/rails_6.0/Gemfile +5 -0
  15. data/gemfiles/rails_6.1/Gemfile +5 -0
  16. data/gemfiles/rails_7.0/Gemfile +5 -0
  17. data/gemfiles/rails_7.1/Gemfile +5 -0
  18. data/gemfiles/rails_edge/Gemfile +13 -0
  19. data/lib/formtastic/action_class_finder.rb +1 -0
  20. data/lib/formtastic/actions/base.rb +1 -0
  21. data/lib/formtastic/actions/button_action.rb +1 -0
  22. data/lib/formtastic/actions/buttonish.rb +1 -0
  23. data/lib/formtastic/actions/input_action.rb +1 -0
  24. data/lib/formtastic/actions/link_action.rb +1 -0
  25. data/lib/formtastic/actions.rb +7 -3
  26. data/lib/formtastic/deprecation.rb +2 -38
  27. data/lib/formtastic/engine.rb +4 -1
  28. data/lib/formtastic/form_builder.rb +12 -24
  29. data/lib/formtastic/helpers/action_helper.rb +2 -48
  30. data/lib/formtastic/helpers/actions_helper.rb +1 -0
  31. data/lib/formtastic/helpers/enum.rb +14 -0
  32. data/lib/formtastic/helpers/errors_helper.rb +3 -2
  33. data/lib/formtastic/helpers/fieldset_wrapper.rb +14 -9
  34. data/lib/formtastic/helpers/file_column_detection.rb +1 -0
  35. data/lib/formtastic/helpers/form_helper.rb +2 -1
  36. data/lib/formtastic/helpers/input_helper.rb +20 -76
  37. data/lib/formtastic/helpers/inputs_helper.rb +29 -23
  38. data/lib/formtastic/helpers/reflection.rb +1 -0
  39. data/lib/formtastic/helpers.rb +2 -2
  40. data/lib/formtastic/html_attributes.rb +1 -0
  41. data/lib/formtastic/i18n.rb +2 -1
  42. data/lib/formtastic/input_class_finder.rb +1 -0
  43. data/lib/formtastic/inputs/base/associations.rb +1 -0
  44. data/lib/formtastic/inputs/base/choices.rb +3 -2
  45. data/lib/formtastic/inputs/base/collections.rb +46 -10
  46. data/lib/formtastic/inputs/base/database.rb +5 -7
  47. data/lib/formtastic/inputs/base/datetime_pickerish.rb +1 -0
  48. data/lib/formtastic/inputs/base/errors.rb +7 -6
  49. data/lib/formtastic/inputs/base/fileish.rb +1 -0
  50. data/lib/formtastic/inputs/base/hints.rb +2 -1
  51. data/lib/formtastic/inputs/base/html.rb +9 -7
  52. data/lib/formtastic/inputs/base/labelling.rb +3 -2
  53. data/lib/formtastic/inputs/base/naming.rb +5 -4
  54. data/lib/formtastic/inputs/base/numeric.rb +1 -0
  55. data/lib/formtastic/inputs/base/options.rb +3 -3
  56. data/lib/formtastic/inputs/base/placeholder.rb +1 -0
  57. data/lib/formtastic/inputs/base/stringish.rb +1 -0
  58. data/lib/formtastic/inputs/base/timeish.rb +9 -4
  59. data/lib/formtastic/inputs/base/validations.rb +39 -12
  60. data/lib/formtastic/inputs/base/wrapping.rb +1 -0
  61. data/lib/formtastic/inputs/base.rb +3 -2
  62. data/lib/formtastic/inputs/boolean_input.rb +2 -1
  63. data/lib/formtastic/inputs/check_boxes_input.rb +15 -6
  64. data/lib/formtastic/inputs/color_input.rb +1 -1
  65. data/lib/formtastic/inputs/country_input.rb +4 -1
  66. data/lib/formtastic/inputs/datalist_input.rb +1 -0
  67. data/lib/formtastic/inputs/date_picker_input.rb +1 -0
  68. data/lib/formtastic/inputs/date_select_input.rb +1 -0
  69. data/lib/formtastic/inputs/datetime_picker_input.rb +1 -0
  70. data/lib/formtastic/inputs/datetime_select_input.rb +1 -0
  71. data/lib/formtastic/inputs/email_input.rb +1 -0
  72. data/lib/formtastic/inputs/file_input.rb +1 -0
  73. data/lib/formtastic/inputs/hidden_input.rb +3 -2
  74. data/lib/formtastic/inputs/number_input.rb +1 -0
  75. data/lib/formtastic/inputs/password_input.rb +1 -0
  76. data/lib/formtastic/inputs/phone_input.rb +1 -0
  77. data/lib/formtastic/inputs/radio_input.rb +21 -0
  78. data/lib/formtastic/inputs/range_input.rb +1 -0
  79. data/lib/formtastic/inputs/search_input.rb +1 -0
  80. data/lib/formtastic/inputs/select_input.rb +30 -1
  81. data/lib/formtastic/inputs/string_input.rb +1 -0
  82. data/lib/formtastic/inputs/text_input.rb +1 -0
  83. data/lib/formtastic/inputs/time_picker_input.rb +1 -0
  84. data/lib/formtastic/inputs/time_select_input.rb +1 -0
  85. data/lib/formtastic/inputs/time_zone_input.rb +17 -6
  86. data/lib/formtastic/inputs/url_input.rb +1 -0
  87. data/lib/formtastic/inputs.rb +33 -29
  88. data/lib/formtastic/localized_string.rb +1 -0
  89. data/lib/formtastic/localizer.rb +21 -22
  90. data/lib/formtastic/namespaced_class_finder.rb +8 -9
  91. data/lib/formtastic/version.rb +2 -1
  92. data/lib/formtastic.rb +10 -11
  93. data/lib/generators/formtastic/form/form_generator.rb +2 -1
  94. data/lib/generators/formtastic/input/input_generator.rb +47 -0
  95. data/lib/generators/formtastic/install/install_generator.rb +1 -0
  96. data/lib/generators/templates/formtastic.rb +15 -13
  97. data/lib/generators/templates/input.rb +19 -0
  98. data/sample/basic_inputs.html +1 -1
  99. data/script/integration-template.rb +73 -0
  100. data/script/integration.sh +19 -0
  101. data/spec/action_class_finder_spec.rb +2 -1
  102. data/spec/actions/button_action_spec.rb +21 -20
  103. data/spec/actions/generic_action_spec.rb +134 -133
  104. data/spec/actions/input_action_spec.rb +20 -19
  105. data/spec/actions/link_action_spec.rb +30 -29
  106. data/spec/builder/custom_builder_spec.rb +39 -22
  107. data/spec/builder/error_proc_spec.rb +6 -5
  108. data/spec/builder/semantic_fields_for_spec.rb +46 -45
  109. data/spec/fast_spec_helper.rb +13 -0
  110. data/spec/generators/formtastic/form/form_generator_spec.rb +33 -32
  111. data/spec/generators/formtastic/input/input_generator_spec.rb +125 -0
  112. data/spec/generators/formtastic/install/install_generator_spec.rb +10 -9
  113. data/spec/helpers/action_helper_spec.rb +329 -10
  114. data/spec/helpers/actions_helper_spec.rb +43 -42
  115. data/spec/helpers/form_helper_spec.rb +45 -38
  116. data/spec/helpers/input_helper_spec.rb +976 -2
  117. data/spec/helpers/inputs_helper_spec.rb +217 -202
  118. data/spec/helpers/reflection_helper_spec.rb +7 -6
  119. data/spec/helpers/semantic_errors_helper_spec.rb +26 -25
  120. data/spec/i18n_spec.rb +30 -29
  121. data/spec/input_class_finder_spec.rb +2 -1
  122. data/spec/inputs/base/collections_spec.rb +78 -0
  123. data/spec/inputs/base/validations_spec.rb +481 -0
  124. data/spec/inputs/boolean_input_spec.rb +73 -72
  125. data/spec/inputs/check_boxes_input_spec.rb +169 -121
  126. data/spec/inputs/color_input_spec.rb +53 -64
  127. data/spec/inputs/country_input_spec.rb +23 -22
  128. data/spec/inputs/custom_input_spec.rb +3 -6
  129. data/spec/inputs/datalist_input_spec.rb +3 -2
  130. data/spec/inputs/date_picker_input_spec.rb +114 -113
  131. data/spec/inputs/date_select_input_spec.rb +76 -61
  132. data/spec/inputs/datetime_picker_input_spec.rb +123 -122
  133. data/spec/inputs/datetime_select_input_spec.rb +85 -68
  134. data/spec/inputs/email_input_spec.rb +17 -16
  135. data/spec/inputs/file_input_spec.rb +18 -17
  136. data/spec/inputs/hidden_input_spec.rb +32 -31
  137. data/spec/inputs/include_blank_spec.rb +10 -9
  138. data/spec/inputs/label_spec.rb +26 -25
  139. data/spec/inputs/number_input_spec.rb +212 -211
  140. data/spec/inputs/password_input_spec.rb +17 -16
  141. data/spec/inputs/phone_input_spec.rb +17 -16
  142. data/spec/inputs/placeholder_spec.rb +18 -17
  143. data/spec/inputs/radio_input_spec.rb +92 -65
  144. data/spec/inputs/range_input_spec.rb +136 -135
  145. data/spec/inputs/readonly_spec.rb +51 -0
  146. data/spec/inputs/search_input_spec.rb +16 -15
  147. data/spec/inputs/select_input_spec.rb +209 -102
  148. data/spec/inputs/string_input_spec.rb +51 -50
  149. data/spec/inputs/text_input_spec.rb +34 -33
  150. data/spec/inputs/time_picker_input_spec.rb +115 -114
  151. data/spec/inputs/time_select_input_spec.rb +84 -70
  152. data/spec/inputs/time_zone_input_spec.rb +58 -31
  153. data/spec/inputs/url_input_spec.rb +17 -16
  154. data/spec/inputs/with_options_spec.rb +9 -8
  155. data/spec/localizer_spec.rb +18 -17
  156. data/spec/namespaced_class_finder_spec.rb +18 -6
  157. data/spec/schema.rb +22 -0
  158. data/spec/spec_helper.rb +172 -260
  159. data/spec/support/custom_macros.rb +74 -76
  160. data/spec/support/deprecation.rb +2 -1
  161. data/spec/support/shared_examples.rb +2 -1233
  162. data/spec/support/specialized_class_finder_shared_example.rb +1 -0
  163. data/spec/support/test_environment.rb +24 -9
  164. metadata +78 -170
  165. data/.travis.yml +0 -29
  166. data/Appraisals +0 -29
  167. data/CHANGELOG +0 -39
  168. data/DEPRECATIONS +0 -49
  169. data/gemfiles/rails_3.2.gemfile +0 -7
  170. data/gemfiles/rails_4.0.4.gemfile +0 -7
  171. data/gemfiles/rails_4.1.gemfile +0 -7
  172. data/gemfiles/rails_4.2.gemfile +0 -7
  173. data/gemfiles/rails_4.gemfile +0 -7
  174. data/gemfiles/rails_edge.gemfile +0 -10
  175. data/lib/formtastic/util.rb +0 -57
  176. data/spec/helpers/namespaced_action_helper_spec.rb +0 -43
  177. data/spec/helpers/namespaced_input_helper_spec.rb +0 -36
  178. data/spec/support/deferred_garbage_collection.rb +0 -21
  179. data/spec/util_spec.rb +0 -66
@@ -1,12 +1,13 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
4
5
  module Naming
5
6
 
6
7
  def as
7
- self.class.name.split("::").last.underscore.gsub(/_input$/, '')
8
+ self.class.name.split("::")[-1].underscore.gsub(/_input$/, '')
8
9
  end
9
-
10
+
10
11
  def sanitized_object_name
11
12
  object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
12
13
  end
@@ -18,7 +19,7 @@ module Formtastic
18
19
  def attributized_method_name
19
20
  method.to_s.gsub(/_id$/, '').to_sym
20
21
  end
21
-
22
+
22
23
  def humanized_method_name
23
24
  if builder.label_str_method != :humanize
24
25
  # Special case where label_str_method should trump the human_attribute_name
@@ -39,4 +40,4 @@ module Formtastic
39
40
  end
40
41
  end
41
42
  end
42
- end
43
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
@@ -1,16 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
4
5
  module Options
5
-
6
+
6
7
  def input_options
7
8
  options.except(*formtastic_options)
8
9
  end
9
-
10
+
10
11
  def formtastic_options
11
12
  [:priority_countries, :priority_zones, :member_label, :member_value, :collection, :required, :label, :as, :hint, :input_html, :value_as_class, :class]
12
13
  end
13
-
14
14
  end
15
15
  end
16
16
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
@@ -85,6 +86,9 @@ module Formtastic
85
86
  # <%= f.input :publish_at, :as => :time_select, :include_blank => true %>
86
87
  # <%= f.input :publish_at, :as => :time_select, :include_blank => false %>
87
88
  #
89
+ # @example Provide a value for the field via selected
90
+ # <%= f.input :publish_at, :as => :datetime_select, :selected => DateTime.new(2018, 10, 4, 12, 00)
91
+ #
88
92
  # @todo Document i18n
89
93
  # @todo Check what other Rails options are supported (`start_year`, `end_year`, `use_month_numbers`, `use_short_month`, `add_month_numbers`, `prompt`), write tests for them, and otherwise support them
90
94
  # @todo Could we take the rendering from Rails' helpers and inject better HTML in and around it rather than re-inventing the whee?
@@ -153,10 +157,11 @@ module Formtastic
153
157
 
154
158
  def fragment_label_html(fragment)
155
159
  text = fragment_label(fragment)
156
- text.blank? ? "".html_safe : template.content_tag(:label, text, :for => fragment_id(fragment))
160
+ text.blank? ? +"".html_safe : template.content_tag(:label, text, :for => fragment_id(fragment))
157
161
  end
158
162
 
159
163
  def value
164
+ return input_options[:selected] if options.key?(:selected)
160
165
  object.send(method) if object && object.respond_to?(method)
161
166
  end
162
167
 
@@ -213,7 +218,7 @@ module Formtastic
213
218
  :class => "label"
214
219
  )
215
220
  else
216
- "".html_safe
221
+ +"".html_safe
217
222
  end
218
223
  end
219
224
 
@@ -224,7 +229,7 @@ module Formtastic
224
229
  end
225
230
 
226
231
  def hidden_fragments
227
- "".html_safe
232
+ +"".html_safe
228
233
  end
229
234
 
230
235
  def hidden_field_name(fragment)
@@ -238,4 +243,4 @@ module Formtastic
238
243
  end
239
244
  end
240
245
  end
241
- end
246
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
@@ -73,13 +74,11 @@ module Formtastic
73
74
  raise IndeterminableMinimumAttributeError if validation.options[:greater_than] && column? && [:float, :decimal].include?(column.type)
74
75
 
75
76
  if validation.options[:greater_than_or_equal_to]
76
- return (validation.options[:greater_than_or_equal_to].call(object)) if validation.options[:greater_than_or_equal_to].kind_of?(Proc)
77
- return (validation.options[:greater_than_or_equal_to])
77
+ return option_value(validation.options[:greater_than_or_equal_to], object)
78
78
  end
79
79
 
80
80
  if validation.options[:greater_than]
81
- return (validation.options[:greater_than].call(object) + 1) if validation.options[:greater_than].kind_of?(Proc)
82
- return (validation.options[:greater_than] + 1)
81
+ return option_value(validation.options[:greater_than], object) + 1
83
82
  end
84
83
  end
85
84
  end
@@ -94,13 +93,11 @@ module Formtastic
94
93
  raise IndeterminableMaximumAttributeError if validation.options[:less_than] && column? && [:float, :decimal].include?(column.type)
95
94
 
96
95
  if validation.options[:less_than_or_equal_to]
97
- return (validation.options[:less_than_or_equal_to].call(object)) if validation.options[:less_than_or_equal_to].kind_of?(Proc)
98
- return (validation.options[:less_than_or_equal_to])
96
+ return option_value(validation.options[:less_than_or_equal_to], object)
99
97
  end
100
98
 
101
99
  if validation.options[:less_than]
102
- return ((validation.options[:less_than].call(object)) - 1) if validation.options[:less_than].kind_of?(Proc)
103
- return (validation.options[:less_than] - 1)
100
+ return option_value(validation.options[:less_than], object) - 1
104
101
  end
105
102
  end
106
103
  end
@@ -136,9 +133,10 @@ module Formtastic
136
133
  return true if options[:required] == true
137
134
  return false if not_required_through_negated_validation?
138
135
  if validations?
139
- validations.select { |validator|
136
+ validations.any? { |validator|
140
137
  if validator.options.key?(:on)
141
- return false if (validator.options[:on] != :save) && ((object.new_record? && validator.options[:on] != :create) || (!object.new_record? && validator.options[:on] != :update))
138
+ validator_on = Array(validator.options[:on])
139
+ next false if (validator_on.exclude?(:save)) && ((object.new_record? && validator_on.exclude?(:create)) || (!object.new_record? && validator_on.exclude?(:update)))
142
140
  end
143
141
  case validator.kind
144
142
  when :presence
@@ -152,7 +150,7 @@ module Formtastic
152
150
  else
153
151
  false
154
152
  end
155
- }.any?
153
+ }
156
154
  else
157
155
  return responds_to_global_required? && !!builder.all_fields_required_by_default
158
156
  end
@@ -192,8 +190,37 @@ module Formtastic
192
190
  validation_limit || column_limit
193
191
  end
194
192
 
193
+ def readonly?
194
+ readonly_from_options? || readonly_attribute?
195
+ end
196
+
197
+ def readonly_attribute?
198
+ object_class = self.object.class
199
+ object_class.respond_to?(:readonly_attributes) &&
200
+ self.object.persisted? &&
201
+ column.respond_to?(:name) &&
202
+ object_class.readonly_attributes.include?(column.name.to_s)
203
+ end
204
+
205
+ def readonly_from_options?
206
+ options[:input_html] && options[:input_html][:readonly]
207
+ end
208
+
209
+ private
210
+
211
+ # Loosely based on
212
+ # https://github.com/rails/rails/blob/459e7cf62252558bbf65f582a230562ab1a76c5e/activemodel/lib/active_model/validations/numericality.rb#L65-L70
213
+ def option_value(option, object)
214
+ case option
215
+ when Symbol
216
+ object.send(option)
217
+ when Proc
218
+ option.call(object)
219
+ else
220
+ option
221
+ end
222
+ end
195
223
  end
196
224
  end
197
225
  end
198
226
  end
199
-
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  module Base
@@ -21,7 +22,7 @@ module Formtastic
21
22
  # Usefull for deprecating options.
22
23
  def warn_and_correct_option!(old_option_name, new_option_name)
23
24
  if options.key?(old_option_name)
24
- ::ActiveSupport::Deprecation.warn("The :#{old_option_name} option is deprecated in favour of :#{new_option_name} and will be removed from Formtastic in the next version", caller(6))
25
+ Deprecation.warn("The :#{old_option_name} option is deprecated in favour of :#{new_option_name} and will be removed from Formtastic in the next version", caller(6))
25
26
  options[new_option_name] = options.delete(old_option_name)
26
27
  end
27
28
  end
@@ -29,7 +30,7 @@ module Formtastic
29
30
  # Usefull for deprecating options.
30
31
  def warn_deprecated_option!(old_option_name, instructions)
31
32
  if options.key?(old_option_name)
32
- ::ActiveSupport::Deprecation.warn("The :#{old_option_name} option is deprecated in favour of `#{instructions}`. :#{old_option_name} will be removed in the next version", caller(6))
33
+ Deprecation.warn("The :#{old_option_name} option is deprecated in favour of `#{instructions}`. :#{old_option_name} will be removed in the next version", caller(6))
33
34
  end
34
35
  end
35
36
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  # Boolean inputs are used to render an input for a single checkbox, typically for attributes
@@ -59,7 +60,7 @@ module Formtastic
59
60
  end
60
61
 
61
62
  def label_text_with_embedded_checkbox
62
- check_box_html << "" << label_text
63
+ check_box_html << +"" << label_text
63
64
  end
64
65
 
65
66
  def check_box_html
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -69,6 +70,11 @@ module Formtastic
69
70
  include Base::Collections
70
71
  include Base::Choices
71
72
 
73
+ def initialize(*args)
74
+ super
75
+ raise Formtastic::UnsupportedEnumCollection if collection_from_enum?
76
+ end
77
+
72
78
  def to_html
73
79
  input_wrapping do
74
80
  choices_wrapping do
@@ -94,8 +100,8 @@ module Formtastic
94
100
  end
95
101
 
96
102
  def hidden_field_for_all
97
- if hidden_fields?
98
- ''
103
+ if hidden_fields_for_every?
104
+ +''
99
105
  else
100
106
  options = {}
101
107
  options[:class] = [method.to_s.singularize, 'default'].join('_') if value_as_class?
@@ -104,7 +110,7 @@ module Formtastic
104
110
  end
105
111
  end
106
112
 
107
- def hidden_fields?
113
+ def hidden_fields_for_every?
108
114
  options[:hidden_fields]
109
115
  end
110
116
 
@@ -165,7 +171,7 @@ module Formtastic
165
171
  protected
166
172
 
167
173
  def checkbox_input(choice)
168
- if hidden_fields?
174
+ if hidden_fields_for_every?
169
175
  check_box_with_hidden_input(choice)
170
176
  else
171
177
  check_box_without_hidden_input(choice)
@@ -175,11 +181,14 @@ module Formtastic
175
181
  def make_selected_values
176
182
  if object.respond_to?(method)
177
183
  selected_items = object.send(method)
178
-
179
184
  # Construct an array from the return value, regardless of the return type
180
185
  selected_items = [*selected_items].compact.flatten
181
186
 
182
- [*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
187
+ selected = []
188
+ selected_items.map do |selected_item|
189
+ selected_item_id = selected_item.id if selected_item.respond_to? :id
190
+ item = send_or_call_or_object(value_method, selected_item) || selected_item_id
191
+ end.compact
183
192
  else
184
193
  []
185
194
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -31,7 +32,6 @@ module Formtastic
31
32
  include Base::Placeholder
32
33
 
33
34
  def to_html
34
- raise "The :color input requires the color_field form helper, which is only available in Rails 4+" unless builder.respond_to?(:color_field)
35
35
  input_wrapping do
36
36
  label_html <<
37
37
  builder.color_field(method, input_html_options)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  # Outputs a country select input, wrapping around a regular country_select helper.
@@ -67,8 +68,10 @@ module Formtastic
67
68
  class CountryInput
68
69
  include Base
69
70
 
71
+ CountrySelectPluginMissing = Class.new(StandardError)
72
+
70
73
  def to_html
71
- raise "To use the :country input, please install a country_select plugin, like this one: https://github.com/stefanpenner/country_select" unless builder.respond_to?(:country_select)
74
+ raise CountrySelectPluginMissing, "To use the :country input, please install a country_select plugin, like this one: https://github.com/stefanpenner/country_select" unless builder.respond_to?(:country_select)
72
75
  input_wrapping do
73
76
  label_html <<
74
77
  builder.country_select(method, priority_countries, input_options, input_html_options)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  # Outputs a label and a text field, along with a datalist tag
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  # Outputs a series of select boxes for the fragments that make up a date (year, month, day).
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -42,7 +43,7 @@ module Formtastic
42
43
  end
43
44
 
44
45
  def error_html
45
- ""
46
+ +""
46
47
  end
47
48
 
48
49
  def errors?
@@ -50,7 +51,7 @@ module Formtastic
50
51
  end
51
52
 
52
53
  def hint_html
53
- ""
54
+ +""
54
55
  end
55
56
 
56
57
  def hint?
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -31,6 +32,10 @@ module Formtastic
31
32
  # `Section.all` for a `Post` form with an input for a `belongs_to :section` association.
32
33
  # You can override or customise this collection through the `:collection` option (see examples).
33
34
  #
35
+ # For radio inputs that map to ActiveRecord `enum` attributes, Formtastic will automatically
36
+ # load in your enum options to be used as the radio button choices. This can be overridden with
37
+ # the `:collection` option, or augmented with I18n translations. See examples below.
38
+ #
34
39
  # The way on which Formtastic renders the `value` attribute and label for each choice in the `:collection` is
35
40
  # customisable (see examples below). When not provided, we fall back to a list of methods to try on each
36
41
  # object such as `:to_label`, `:name` and `:to_s`, which are defined in the configurations
@@ -100,6 +105,22 @@ module Formtastic
100
105
  # @example Set HTML options on a specific radio input option with a 3rd element in the array for a collection member
101
106
  # <%= f.input :author, :as => :radio, :collection => [["Test", 'test'], ["Try", "try", {:disabled => true}]]
102
107
  #
108
+ # @example Using ActiveRecord enum attribute with i18n translation:
109
+ # # post.rb
110
+ # class Post < ActiveRecord::Base
111
+ # enum :status => [ :active, :archived ]
112
+ # end
113
+ # # en.yml
114
+ # en:
115
+ # activerecord:
116
+ # attributes:
117
+ # post:
118
+ # statuses:
119
+ # active: I am active!
120
+ # archived: I am archived!
121
+ # # form
122
+ # <%= f.input :status, :as => :radio %>
123
+ #
103
124
  # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
104
125
  # @see Formtastic::Inputs::RadioInput as an alternative for `belongs_to` associations
105
126
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  # A select input is used to render a `<select>` tag with a series of options to choose from.
@@ -8,6 +9,7 @@ module Formtastic
8
9
  # This is the default input choice when:
9
10
  #
10
11
  # * the database column type is an `:integer` and there is an association (`belongs_to`)
12
+ # * the database column type is an `:integer` and there is an enum defined (`enum`)
11
13
  # * the database column type is a `:string` and the `:collection` option is used
12
14
  # * there an object with an association, but no database column on the object (`has_many`, etc)
13
15
  # * there is no object and the `:collection` option is used
@@ -38,6 +40,13 @@ module Formtastic
38
40
  # `:to_s`, which are defined in the configurations `collection_label_methods` and
39
41
  # `collection_value_methods` (see examples below).
40
42
  #
43
+ # For select inputs that map to ActiveRecord `enum` attributes, Formtastic will automatically
44
+ # load in your enum options to be used as the select's options. This can be overridden with
45
+ # the `:collection` option, or augmented with I18n translations. See examples below.
46
+ # An error is raised if you try to render a multi-select with an enum, as ActiveRecord can
47
+ # only store one choice in the database.
48
+ #
49
+ #
41
50
  # @example Basic `belongs_to` example with full form context
42
51
  #
43
52
  # <%= semantic_form_for @post do |f| %>
@@ -124,6 +133,21 @@ module Formtastic
124
133
  # <%= f.input :author, :as => :select, :prompt => true %> => <option value="">Please select</option>
125
134
  # <%= f.input :author, :as => :select, :prompt => "Please select an author" %>
126
135
  #
136
+ # @example Using ActiveRecord enum attribute with i18n translation:
137
+ # # post.rb
138
+ # class Post < ActiveRecord::Base
139
+ # enum :status => [ :active, :archived ]
140
+ # end
141
+ # # en.yml
142
+ # en:
143
+ # activerecord:
144
+ # attributes:
145
+ # post:
146
+ # statuses:
147
+ # active: I am active!
148
+ # archived: I am archived!
149
+ # # form
150
+ # <%= f.input :status, :as => :select %>
127
151
  #
128
152
  # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
129
153
  # @see Formtastic::Inputs::CheckBoxesInput CheckBoxesInput as an alternative for `has_many` and `has_and_belongs_to_many` associations
@@ -134,6 +158,11 @@ module Formtastic
134
158
  include Base
135
159
  include Base::Collections
136
160
 
161
+ def initialize(*args)
162
+ super
163
+ raise Formtastic::UnsupportedEnumCollection if collection_from_enum? && multiple?
164
+ end
165
+
137
166
  def to_html
138
167
  input_wrapping do
139
168
  label_html <<
@@ -168,7 +197,7 @@ module Formtastic
168
197
  def extra_input_html_options
169
198
  {
170
199
  :multiple => multiple?,
171
- :name => (multiple? && Rails::VERSION::MAJOR >= 3) ? input_html_options_name_multiple : input_html_options_name
200
+ :name => multiple? ? input_html_options_name_multiple : input_html_options_name
172
201
  }
173
202
 
174
203
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
  # Outputs a series of select boxes for the fragments that make up a time (hour, minute, second).
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4
 
@@ -28,9 +29,19 @@ module Formtastic
28
29
  #
29
30
  # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
30
31
  #
31
- # @todo document :priority_zones option
32
- # @todo configurable default :priority_zones?
33
- class TimeZoneInput
32
+ # The priority_zones option:
33
+ # Since this input actually uses Rails' `time_zone_select` helper, the :priority_zones
34
+ # option needs to be an array of ActiveSupport::TimeZone objects.
35
+ #
36
+ # And you can configure default value using
37
+ #
38
+ # ```
39
+ # Formtastic::FormBuilder.priority_time_zones = [timezone1, timezone2]
40
+ # ```
41
+ #
42
+ # See http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/time_zone_select for more information.
43
+ #
44
+ class TimeZoneInput
34
45
  include Base
35
46
 
36
47
  def to_html
@@ -39,10 +50,10 @@ module Formtastic
39
50
  builder.time_zone_select(method, priority_zones, input_options, input_html_options)
40
51
  end
41
52
  end
42
-
53
+
43
54
  def priority_zones
44
- options[:priority_zones] || [] # TODO config?
55
+ options[:priority_zones] || Formtastic::FormBuilder.priority_time_zones
45
56
  end
46
57
  end
47
58
  end
48
- end
59
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Formtastic
2
3
  module Inputs
3
4