formtastic 3.1.2 → 4.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 (135) 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 +52 -0
  6. data/Gemfile.lock +105 -0
  7. data/MIT-LICENSE +1 -1
  8. data/{README.textile → README.md} +178 -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 +10 -16
  14. data/gemfiles/rails_5.2/Gemfile +5 -0
  15. data/gemfiles/rails_6.0/Gemfile +5 -0
  16. data/gemfiles/rails_6.1/Gemfile +5 -0
  17. data/gemfiles/rails_edge/Gemfile +13 -0
  18. data/lib/formtastic.rb +9 -11
  19. data/lib/formtastic/actions.rb +6 -3
  20. data/lib/formtastic/deprecation.rb +1 -38
  21. data/lib/formtastic/engine.rb +3 -1
  22. data/lib/formtastic/form_builder.rb +11 -24
  23. data/lib/formtastic/helpers.rb +1 -1
  24. data/lib/formtastic/helpers/action_helper.rb +1 -48
  25. data/lib/formtastic/helpers/enum.rb +13 -0
  26. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  27. data/lib/formtastic/helpers/fieldset_wrapper.rb +13 -9
  28. data/lib/formtastic/helpers/form_helper.rb +1 -1
  29. data/lib/formtastic/helpers/input_helper.rb +23 -77
  30. data/lib/formtastic/helpers/inputs_helper.rb +27 -22
  31. data/lib/formtastic/i18n.rb +1 -1
  32. data/lib/formtastic/inputs.rb +32 -29
  33. data/lib/formtastic/inputs/base/choices.rb +1 -1
  34. data/lib/formtastic/inputs/base/collections.rb +43 -10
  35. data/lib/formtastic/inputs/base/database.rb +7 -2
  36. data/lib/formtastic/inputs/base/errors.rb +4 -4
  37. data/lib/formtastic/inputs/base/hints.rb +1 -1
  38. data/lib/formtastic/inputs/base/html.rb +7 -6
  39. data/lib/formtastic/inputs/base/naming.rb +4 -4
  40. data/lib/formtastic/inputs/base/options.rb +2 -3
  41. data/lib/formtastic/inputs/base/timeish.rb +5 -1
  42. data/lib/formtastic/inputs/base/validations.rb +38 -12
  43. data/lib/formtastic/inputs/check_boxes_input.rb +13 -5
  44. data/lib/formtastic/inputs/color_input.rb +0 -1
  45. data/lib/formtastic/inputs/country_input.rb +3 -1
  46. data/lib/formtastic/inputs/radio_input.rb +20 -0
  47. data/lib/formtastic/inputs/select_input.rb +29 -1
  48. data/lib/formtastic/inputs/time_zone_input.rb +16 -6
  49. data/lib/formtastic/localizer.rb +20 -22
  50. data/lib/formtastic/namespaced_class_finder.rb +1 -1
  51. data/lib/formtastic/version.rb +1 -1
  52. data/lib/generators/formtastic/form/form_generator.rb +1 -1
  53. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  54. data/lib/generators/templates/formtastic.rb +14 -13
  55. data/lib/generators/templates/input.rb +19 -0
  56. data/sample/basic_inputs.html +1 -1
  57. data/script/integration-template.rb +74 -0
  58. data/script/integration.sh +19 -0
  59. data/spec/action_class_finder_spec.rb +1 -1
  60. data/spec/actions/button_action_spec.rb +8 -8
  61. data/spec/actions/generic_action_spec.rb +60 -60
  62. data/spec/actions/input_action_spec.rb +7 -7
  63. data/spec/actions/link_action_spec.rb +10 -10
  64. data/spec/builder/custom_builder_spec.rb +37 -21
  65. data/spec/builder/error_proc_spec.rb +4 -4
  66. data/spec/builder/semantic_fields_for_spec.rb +27 -27
  67. data/spec/fast_spec_helper.rb +12 -0
  68. data/spec/generators/formtastic/form/form_generator_spec.rb +25 -25
  69. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  70. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  71. data/spec/helpers/action_helper_spec.rb +328 -10
  72. data/spec/helpers/actions_helper_spec.rb +17 -17
  73. data/spec/helpers/form_helper_spec.rb +37 -37
  74. data/spec/helpers/input_helper_spec.rb +975 -2
  75. data/spec/helpers/inputs_helper_spec.rb +120 -105
  76. data/spec/helpers/reflection_helper_spec.rb +3 -3
  77. data/spec/helpers/semantic_errors_helper_spec.rb +22 -22
  78. data/spec/i18n_spec.rb +26 -26
  79. data/spec/input_class_finder_spec.rb +1 -1
  80. data/spec/inputs/base/collections_spec.rb +76 -0
  81. data/spec/inputs/base/validations_spec.rb +480 -0
  82. data/spec/inputs/boolean_input_spec.rb +55 -55
  83. data/spec/inputs/check_boxes_input_spec.rb +155 -108
  84. data/spec/inputs/color_input_spec.rb +51 -63
  85. data/spec/inputs/country_input_spec.rb +20 -20
  86. data/spec/inputs/custom_input_spec.rb +2 -6
  87. data/spec/inputs/datalist_input_spec.rb +1 -1
  88. data/spec/inputs/date_picker_input_spec.rb +42 -42
  89. data/spec/inputs/date_select_input_spec.rb +51 -37
  90. data/spec/inputs/datetime_picker_input_spec.rb +46 -46
  91. data/spec/inputs/datetime_select_input_spec.rb +53 -37
  92. data/spec/inputs/email_input_spec.rb +5 -5
  93. data/spec/inputs/file_input_spec.rb +6 -6
  94. data/spec/inputs/hidden_input_spec.rb +18 -18
  95. data/spec/inputs/include_blank_spec.rb +8 -8
  96. data/spec/inputs/label_spec.rb +20 -20
  97. data/spec/inputs/number_input_spec.rb +112 -112
  98. data/spec/inputs/password_input_spec.rb +5 -5
  99. data/spec/inputs/phone_input_spec.rb +5 -5
  100. data/spec/inputs/placeholder_spec.rb +5 -5
  101. data/spec/inputs/radio_input_spec.rb +84 -58
  102. data/spec/inputs/range_input_spec.rb +66 -66
  103. data/spec/inputs/readonly_spec.rb +50 -0
  104. data/spec/inputs/search_input_spec.rb +5 -5
  105. data/spec/inputs/select_input_spec.rb +149 -93
  106. data/spec/inputs/string_input_spec.rb +23 -23
  107. data/spec/inputs/text_input_spec.rb +16 -16
  108. data/spec/inputs/time_picker_input_spec.rb +43 -43
  109. data/spec/inputs/time_select_input_spec.rb +67 -54
  110. data/spec/inputs/time_zone_input_spec.rb +54 -28
  111. data/spec/inputs/url_input_spec.rb +5 -5
  112. data/spec/inputs/with_options_spec.rb +7 -7
  113. data/spec/localizer_spec.rb +17 -17
  114. data/spec/namespaced_class_finder_spec.rb +2 -2
  115. data/spec/schema.rb +21 -0
  116. data/spec/spec_helper.rb +165 -253
  117. data/spec/support/custom_macros.rb +72 -75
  118. data/spec/support/shared_examples.rb +0 -1232
  119. data/spec/support/test_environment.rb +23 -9
  120. metadata +69 -176
  121. data/.travis.yml +0 -29
  122. data/Appraisals +0 -29
  123. data/CHANGELOG +0 -31
  124. data/DEPRECATIONS +0 -49
  125. data/gemfiles/rails_3.2.gemfile +0 -7
  126. data/gemfiles/rails_4.0.4.gemfile +0 -7
  127. data/gemfiles/rails_4.1.gemfile +0 -7
  128. data/gemfiles/rails_4.2.gemfile +0 -7
  129. data/gemfiles/rails_4.gemfile +0 -7
  130. data/gemfiles/rails_edge.gemfile +0 -10
  131. data/lib/formtastic/util.rb +0 -57
  132. data/spec/helpers/namespaced_action_helper_spec.rb +0 -43
  133. data/spec/helpers/namespaced_input_helper_spec.rb +0 -36
  134. data/spec/support/deferred_garbage_collection.rb +0 -21
  135. data/spec/util_spec.rb +0 -66
@@ -4,7 +4,12 @@ module Formtastic
4
4
  module Database
5
5
 
6
6
  def column
7
- object.column_for_attribute(method) if object.respond_to?(:column_for_attribute)
7
+ if object.respond_to?(:column_for_attribute)
8
+ # Remove deprecation wrapper & review after Rails 5.0 ships
9
+ ActiveSupport::Deprecation.silence do
10
+ object.column_for_attribute(method)
11
+ end
12
+ end
8
13
  end
9
14
 
10
15
  def column?
@@ -14,4 +19,4 @@ module Formtastic
14
19
  end
15
20
  end
16
21
  end
17
- end
22
+ end
@@ -9,21 +9,21 @@ module Formtastic
9
9
 
10
10
  def error_sentence_html
11
11
  error_class = builder.default_inline_error_class
12
- template.content_tag(:p, Formtastic::Util.html_safe(errors.to_sentence.html_safe), :class => error_class)
12
+ template.content_tag(:p, errors.to_sentence, :class => error_class)
13
13
  end
14
14
 
15
15
  def error_list_html
16
16
  error_class = builder.default_error_list_class
17
17
  list_elements = []
18
18
  errors.each do |error|
19
- list_elements << template.content_tag(:li, Formtastic::Util.html_safe(error.html_safe))
19
+ list_elements << template.content_tag(:li, error.html_safe)
20
20
  end
21
- template.content_tag(:ul, Formtastic::Util.html_safe(list_elements.join("\n")), :class => error_class)
21
+ template.content_tag(:ul, list_elements.join("\n").html_safe, :class => error_class)
22
22
  end
23
23
 
24
24
  def error_first_html
25
25
  error_class = builder.default_inline_error_class
26
- template.content_tag(:p, Formtastic::Util.html_safe(errors.first.untaint), :class => error_class)
26
+ template.content_tag(:p, errors.first.untaint.html_safe, :class => error_class)
27
27
  end
28
28
 
29
29
  def error_none_html
@@ -7,7 +7,7 @@ module Formtastic
7
7
  if hint?
8
8
  template.content_tag(
9
9
  :p,
10
- Formtastic::Util.html_safe(hint_text),
10
+ hint_text.html_safe,
11
11
  :class => builder.default_hint_class
12
12
  )
13
13
  end
@@ -2,7 +2,7 @@ module Formtastic
2
2
  module Inputs
3
3
  module Base
4
4
  module Html
5
-
5
+
6
6
  # Defines how the instance of an input should be rendered to a HTML string.
7
7
  #
8
8
  # @abstract Implement this method in your input class to describe how the input should render itself.
@@ -17,15 +17,16 @@ module Formtastic
17
17
  def to_html
18
18
  raise NotImplementedError
19
19
  end
20
-
20
+
21
21
  def input_html_options
22
- {
22
+ {
23
23
  :id => dom_id,
24
24
  :required => required_attribute?,
25
- :autofocus => autofocus?
25
+ :autofocus => autofocus?,
26
+ :readonly => readonly?
26
27
  }.merge(options[:input_html] || {})
27
28
  end
28
-
29
+
29
30
  def dom_id
30
31
  [
31
32
  builder.dom_id_namespace,
@@ -34,7 +35,7 @@ module Formtastic
34
35
  association_primary_key || sanitized_method_name
35
36
  ].reject { |x| x.blank? }.join('_')
36
37
  end
37
-
38
+
38
39
  def dom_index
39
40
  if builder.options.has_key?(:index)
40
41
  builder.options[:index]
@@ -4,9 +4,9 @@ module Formtastic
4
4
  module Naming
5
5
 
6
6
  def as
7
- self.class.name.split("::").last.underscore.gsub(/_input$/, '')
7
+ self.class.name.split("::")[-1].underscore.gsub(/_input$/, '')
8
8
  end
9
-
9
+
10
10
  def sanitized_object_name
11
11
  object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
12
12
  end
@@ -18,7 +18,7 @@ module Formtastic
18
18
  def attributized_method_name
19
19
  method.to_s.gsub(/_id$/, '').to_sym
20
20
  end
21
-
21
+
22
22
  def humanized_method_name
23
23
  if builder.label_str_method != :humanize
24
24
  # Special case where label_str_method should trump the human_attribute_name
@@ -39,4 +39,4 @@ module Formtastic
39
39
  end
40
40
  end
41
41
  end
42
- end
42
+ end
@@ -2,15 +2,14 @@ module Formtastic
2
2
  module Inputs
3
3
  module Base
4
4
  module Options
5
-
5
+
6
6
  def input_options
7
7
  options.except(*formtastic_options)
8
8
  end
9
-
9
+
10
10
  def formtastic_options
11
11
  [:priority_countries, :priority_zones, :member_label, :member_value, :collection, :required, :label, :as, :hint, :input_html, :value_as_class, :class]
12
12
  end
13
-
14
13
  end
15
14
  end
16
15
  end
@@ -85,6 +85,9 @@ module Formtastic
85
85
  # <%= f.input :publish_at, :as => :time_select, :include_blank => true %>
86
86
  # <%= f.input :publish_at, :as => :time_select, :include_blank => false %>
87
87
  #
88
+ # @example Provide a value for the field via selected
89
+ # <%= f.input :publish_at, :as => :datetime_select, :selected => DateTime.new(2018, 10, 4, 12, 00)
90
+ #
88
91
  # @todo Document i18n
89
92
  # @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
93
  # @todo Could we take the rendering from Rails' helpers and inject better HTML in and around it rather than re-inventing the whee?
@@ -157,6 +160,7 @@ module Formtastic
157
160
  end
158
161
 
159
162
  def value
163
+ return input_options[:selected] if options.key?(:selected)
160
164
  object.send(method) if object && object.respond_to?(method)
161
165
  end
162
166
 
@@ -238,4 +242,4 @@ module Formtastic
238
242
  end
239
243
  end
240
244
  end
241
- end
245
+ end
@@ -73,13 +73,11 @@ module Formtastic
73
73
  raise IndeterminableMinimumAttributeError if validation.options[:greater_than] && column? && [:float, :decimal].include?(column.type)
74
74
 
75
75
  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])
76
+ return option_value(validation.options[:greater_than_or_equal_to], object)
78
77
  end
79
78
 
80
79
  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)
80
+ return option_value(validation.options[:greater_than], object) + 1
83
81
  end
84
82
  end
85
83
  end
@@ -94,13 +92,11 @@ module Formtastic
94
92
  raise IndeterminableMaximumAttributeError if validation.options[:less_than] && column? && [:float, :decimal].include?(column.type)
95
93
 
96
94
  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])
95
+ return option_value(validation.options[:less_than_or_equal_to], object)
99
96
  end
100
97
 
101
98
  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)
99
+ return option_value(validation.options[:less_than], object) - 1
104
100
  end
105
101
  end
106
102
  end
@@ -136,9 +132,10 @@ module Formtastic
136
132
  return true if options[:required] == true
137
133
  return false if not_required_through_negated_validation?
138
134
  if validations?
139
- validations.select { |validator|
135
+ validations.any? { |validator|
140
136
  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))
137
+ validator_on = Array(validator.options[:on])
138
+ next false if (validator_on.exclude?(:save)) && ((object.new_record? && validator_on.exclude?(:create)) || (!object.new_record? && validator_on.exclude?(:update)))
142
139
  end
143
140
  case validator.kind
144
141
  when :presence
@@ -152,7 +149,7 @@ module Formtastic
152
149
  else
153
150
  false
154
151
  end
155
- }.any?
152
+ }
156
153
  else
157
154
  return responds_to_global_required? && !!builder.all_fields_required_by_default
158
155
  end
@@ -192,8 +189,37 @@ module Formtastic
192
189
  validation_limit || column_limit
193
190
  end
194
191
 
192
+ def readonly?
193
+ readonly_from_options? || readonly_attribute?
194
+ end
195
+
196
+ def readonly_attribute?
197
+ object_class = self.object.class
198
+ object_class.respond_to?(:readonly_attributes) &&
199
+ self.object.persisted? &&
200
+ column.respond_to?(:name) &&
201
+ object_class.readonly_attributes.include?(column.name.to_s)
202
+ end
203
+
204
+ def readonly_from_options?
205
+ options[:input_html] && options[:input_html][:readonly]
206
+ end
207
+
208
+ private
209
+
210
+ # Loosely based on
211
+ # https://github.com/rails/rails/blob/5-2-stable/activemodel/lib/active_model/validations/numericality.rb#L54-L59
212
+ def option_value(option, object)
213
+ case option
214
+ when Symbol
215
+ object.send(option)
216
+ when Proc
217
+ option.call(object)
218
+ else
219
+ option
220
+ end
221
+ end
195
222
  end
196
223
  end
197
224
  end
198
225
  end
199
-
@@ -69,6 +69,11 @@ module Formtastic
69
69
  include Base::Collections
70
70
  include Base::Choices
71
71
 
72
+ def initialize(*args)
73
+ super
74
+ raise Formtastic::UnsupportedEnumCollection if collection_from_enum?
75
+ end
76
+
72
77
  def to_html
73
78
  input_wrapping do
74
79
  choices_wrapping do
@@ -94,7 +99,7 @@ module Formtastic
94
99
  end
95
100
 
96
101
  def hidden_field_for_all
97
- if hidden_fields?
102
+ if hidden_fields_for_every?
98
103
  ''
99
104
  else
100
105
  options = {}
@@ -104,7 +109,7 @@ module Formtastic
104
109
  end
105
110
  end
106
111
 
107
- def hidden_fields?
112
+ def hidden_fields_for_every?
108
113
  options[:hidden_fields]
109
114
  end
110
115
 
@@ -165,7 +170,7 @@ module Formtastic
165
170
  protected
166
171
 
167
172
  def checkbox_input(choice)
168
- if hidden_fields?
173
+ if hidden_fields_for_every?
169
174
  check_box_with_hidden_input(choice)
170
175
  else
171
176
  check_box_without_hidden_input(choice)
@@ -175,11 +180,14 @@ module Formtastic
175
180
  def make_selected_values
176
181
  if object.respond_to?(method)
177
182
  selected_items = object.send(method)
178
-
179
183
  # Construct an array from the return value, regardless of the return type
180
184
  selected_items = [*selected_items].compact.flatten
181
185
 
182
- [*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
186
+ selected = []
187
+ selected_items.map do |selected_item|
188
+ selected_item_id = selected_item.id if selected_item.respond_to? :id
189
+ item = send_or_call_or_object(value_method, selected_item) || selected_item_id
190
+ end.compact
183
191
  else
184
192
  []
185
193
  end
@@ -31,7 +31,6 @@ module Formtastic
31
31
  include Base::Placeholder
32
32
 
33
33
  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
34
  input_wrapping do
36
35
  label_html <<
37
36
  builder.color_field(method, input_html_options)
@@ -67,8 +67,10 @@ module Formtastic
67
67
  class CountryInput
68
68
  include Base
69
69
 
70
+ CountrySelectPluginMissing = Class.new(StandardError)
71
+
70
72
  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)
73
+ 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
74
  input_wrapping do
73
75
  label_html <<
74
76
  builder.country_select(method, priority_countries, input_options, input_html_options)
@@ -31,6 +31,10 @@ module Formtastic
31
31
  # `Section.all` for a `Post` form with an input for a `belongs_to :section` association.
32
32
  # You can override or customise this collection through the `:collection` option (see examples).
33
33
  #
34
+ # For radio inputs that map to ActiveRecord `enum` attributes, Formtastic will automatically
35
+ # load in your enum options to be used as the radio button choices. This can be overridden with
36
+ # the `:collection` option, or augmented with I18n translations. See examples below.
37
+ #
34
38
  # The way on which Formtastic renders the `value` attribute and label for each choice in the `:collection` is
35
39
  # customisable (see examples below). When not provided, we fall back to a list of methods to try on each
36
40
  # object such as `:to_label`, `:name` and `:to_s`, which are defined in the configurations
@@ -100,6 +104,22 @@ module Formtastic
100
104
  # @example Set HTML options on a specific radio input option with a 3rd element in the array for a collection member
101
105
  # <%= f.input :author, :as => :radio, :collection => [["Test", 'test'], ["Try", "try", {:disabled => true}]]
102
106
  #
107
+ # @example Using ActiveRecord enum attribute with i18n translation:
108
+ # # post.rb
109
+ # class Post < ActiveRecord::Base
110
+ # enum :status => [ :active, :archived ]
111
+ # end
112
+ # # en.yml
113
+ # en:
114
+ # activerecord:
115
+ # attributes:
116
+ # post:
117
+ # statuses:
118
+ # active: I am active!
119
+ # archived: I am archived!
120
+ # # form
121
+ # <%= f.input :status, :as => :radio %>
122
+ #
103
123
  # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
104
124
  # @see Formtastic::Inputs::RadioInput as an alternative for `belongs_to` associations
105
125
  #
@@ -8,6 +8,7 @@ module Formtastic
8
8
  # This is the default input choice when:
9
9
  #
10
10
  # * the database column type is an `:integer` and there is an association (`belongs_to`)
11
+ # * the database column type is an `:integer` and there is an enum defined (`enum`)
11
12
  # * the database column type is a `:string` and the `:collection` option is used
12
13
  # * there an object with an association, but no database column on the object (`has_many`, etc)
13
14
  # * there is no object and the `:collection` option is used
@@ -38,6 +39,13 @@ module Formtastic
38
39
  # `:to_s`, which are defined in the configurations `collection_label_methods` and
39
40
  # `collection_value_methods` (see examples below).
40
41
  #
42
+ # For select inputs that map to ActiveRecord `enum` attributes, Formtastic will automatically
43
+ # load in your enum options to be used as the select's options. This can be overridden with
44
+ # the `:collection` option, or augmented with I18n translations. See examples below.
45
+ # An error is raised if you try to render a multi-select with an enum, as ActiveRecord can
46
+ # only store one choice in the database.
47
+ #
48
+ #
41
49
  # @example Basic `belongs_to` example with full form context
42
50
  #
43
51
  # <%= semantic_form_for @post do |f| %>
@@ -124,6 +132,21 @@ module Formtastic
124
132
  # <%= f.input :author, :as => :select, :prompt => true %> => <option value="">Please select</option>
125
133
  # <%= f.input :author, :as => :select, :prompt => "Please select an author" %>
126
134
  #
135
+ # @example Using ActiveRecord enum attribute with i18n translation:
136
+ # # post.rb
137
+ # class Post < ActiveRecord::Base
138
+ # enum :status => [ :active, :archived ]
139
+ # end
140
+ # # en.yml
141
+ # en:
142
+ # activerecord:
143
+ # attributes:
144
+ # post:
145
+ # statuses:
146
+ # active: I am active!
147
+ # archived: I am archived!
148
+ # # form
149
+ # <%= f.input :status, :as => :select %>
127
150
  #
128
151
  # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
129
152
  # @see Formtastic::Inputs::CheckBoxesInput CheckBoxesInput as an alternative for `has_many` and `has_and_belongs_to_many` associations
@@ -134,6 +157,11 @@ module Formtastic
134
157
  include Base
135
158
  include Base::Collections
136
159
 
160
+ def initialize(*args)
161
+ super
162
+ raise Formtastic::UnsupportedEnumCollection if collection_from_enum? && multiple?
163
+ end
164
+
137
165
  def to_html
138
166
  input_wrapping do
139
167
  label_html <<
@@ -168,7 +196,7 @@ module Formtastic
168
196
  def extra_input_html_options
169
197
  {
170
198
  :multiple => multiple?,
171
- :name => (multiple? && Rails::VERSION::MAJOR >= 3) ? input_html_options_name_multiple : input_html_options_name
199
+ :name => multiple? ? input_html_options_name_multiple : input_html_options_name
172
200
  }
173
201
 
174
202
 
@@ -28,9 +28,19 @@ module Formtastic
28
28
  #
29
29
  # @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
30
30
  #
31
- # @todo document :priority_zones option
32
- # @todo configurable default :priority_zones?
33
- class TimeZoneInput
31
+ # The priority_zones option:
32
+ # Since this input actually uses Rails' `time_zone_select` helper, the :priority_zones
33
+ # option needs to be an array of ActiveSupport::TimeZone objects.
34
+ #
35
+ # And you can configure default value using
36
+ #
37
+ # ```
38
+ # Formtastic::FormBuilder.priority_time_zones = [timezone1, timezone2]
39
+ # ```
40
+ #
41
+ # See http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/time_zone_select for more information.
42
+ #
43
+ class TimeZoneInput
34
44
  include Base
35
45
 
36
46
  def to_html
@@ -39,10 +49,10 @@ module Formtastic
39
49
  builder.time_zone_select(method, priority_zones, input_options, input_html_options)
40
50
  end
41
51
  end
42
-
52
+
43
53
  def priority_zones
44
- options[:priority_zones] || [] # TODO config?
54
+ options[:priority_zones] || Formtastic::FormBuilder.priority_time_zones
45
55
  end
46
56
  end
47
57
  end
48
- end
58
+ end