formtastic 2.0.2 → 2.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/.gitignore +4 -1
  2. data/Appraisals +11 -0
  3. data/CHANGELOG +2 -2
  4. data/Gemfile +0 -2
  5. data/README.textile +183 -151
  6. data/Rakefile +9 -5
  7. data/app/assets/stylesheets/formtastic.css +16 -3
  8. data/formtastic.gemspec +6 -2
  9. data/gemfiles/rails-3.0.gemfile +7 -0
  10. data/gemfiles/rails-3.1.gemfile +7 -0
  11. data/gemfiles/rails-3.2.gemfile +7 -0
  12. data/lib/formtastic.rb +10 -2
  13. data/lib/formtastic/actions.rb +11 -0
  14. data/lib/formtastic/actions/base.rb +156 -0
  15. data/lib/formtastic/actions/button_action.rb +72 -0
  16. data/lib/formtastic/actions/buttonish.rb +17 -0
  17. data/lib/formtastic/actions/input_action.rb +68 -0
  18. data/lib/formtastic/actions/link_action.rb +87 -0
  19. data/lib/formtastic/engine.rb +5 -1
  20. data/lib/formtastic/form_builder.rb +3 -0
  21. data/lib/formtastic/helpers.rb +2 -1
  22. data/lib/formtastic/helpers/action_helper.rb +109 -0
  23. data/lib/formtastic/helpers/actions_helper.rb +168 -0
  24. data/lib/formtastic/helpers/buttons_helper.rb +22 -9
  25. data/lib/formtastic/helpers/errors_helper.rb +0 -54
  26. data/lib/formtastic/helpers/fieldset_wrapper.rb +10 -5
  27. data/lib/formtastic/helpers/form_helper.rb +2 -2
  28. data/lib/formtastic/helpers/input_helper.rb +1 -10
  29. data/lib/formtastic/helpers/inputs_helper.rb +6 -3
  30. data/lib/formtastic/i18n.rb +3 -2
  31. data/lib/formtastic/inputs/base.rb +11 -3
  32. data/lib/formtastic/inputs/base/choices.rb +6 -1
  33. data/lib/formtastic/inputs/base/collections.rb +36 -13
  34. data/lib/formtastic/inputs/base/grouped_collections.rb +1 -1
  35. data/lib/formtastic/inputs/base/numeric.rb +50 -0
  36. data/lib/formtastic/inputs/base/options.rb +1 -1
  37. data/lib/formtastic/inputs/base/placeholder.rb +17 -0
  38. data/lib/formtastic/inputs/base/stringish.rb +2 -7
  39. data/lib/formtastic/inputs/base/timeish.rb +21 -5
  40. data/lib/formtastic/inputs/base/validations.rb +1 -1
  41. data/lib/formtastic/inputs/base/wrapping.rb +10 -3
  42. data/lib/formtastic/inputs/boolean_input.rb +10 -2
  43. data/lib/formtastic/inputs/check_boxes_input.rb +18 -9
  44. data/lib/formtastic/inputs/country_input.rb +2 -2
  45. data/lib/formtastic/inputs/date_input.rb +19 -1
  46. data/lib/formtastic/inputs/datetime_input.rb +1 -1
  47. data/lib/formtastic/inputs/email_input.rb +2 -1
  48. data/lib/formtastic/inputs/file_input.rb +1 -1
  49. data/lib/formtastic/inputs/hidden_input.rb +1 -1
  50. data/lib/formtastic/inputs/number_input.rb +6 -36
  51. data/lib/formtastic/inputs/password_input.rb +2 -1
  52. data/lib/formtastic/inputs/phone_input.rb +3 -2
  53. data/lib/formtastic/inputs/radio_input.rb +1 -1
  54. data/lib/formtastic/inputs/range_input.rb +8 -32
  55. data/lib/formtastic/inputs/search_input.rb +2 -1
  56. data/lib/formtastic/inputs/select_input.rb +56 -28
  57. data/lib/formtastic/inputs/string_input.rb +3 -1
  58. data/lib/formtastic/inputs/text_input.rb +5 -4
  59. data/lib/formtastic/inputs/time_input.rb +4 -8
  60. data/lib/formtastic/inputs/time_zone_input.rb +1 -1
  61. data/lib/formtastic/inputs/url_input.rb +2 -1
  62. data/lib/formtastic/localized_string.rb +6 -94
  63. data/lib/formtastic/localizer.rb +110 -0
  64. data/lib/formtastic/version.rb +1 -1
  65. data/lib/generators/formtastic/form/form_generator.rb +105 -0
  66. data/lib/generators/templates/_form.html.erb +2 -2
  67. data/lib/generators/templates/_form.html.haml +4 -4
  68. data/lib/generators/templates/_form.html.slim +2 -2
  69. data/lib/generators/templates/formtastic.rb +4 -0
  70. data/lib/locale/en.yml +2 -0
  71. data/sample/basic_inputs.html +22 -0
  72. data/spec/actions/button_action_spec.rb +63 -0
  73. data/spec/actions/generic_action_spec.rb +484 -0
  74. data/spec/actions/input_action_spec.rb +59 -0
  75. data/spec/actions/link_action_spec.rb +92 -0
  76. data/spec/builder/semantic_fields_for_spec.rb +14 -0
  77. data/spec/generators/formtastic/form/form_generator_spec.rb +118 -0
  78. data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
  79. data/spec/helpers/action_helper_spec.rb +365 -0
  80. data/spec/helpers/actions_helper_spec.rb +143 -0
  81. data/spec/helpers/buttons_helper_spec.rb +39 -23
  82. data/spec/helpers/commit_button_helper_spec.rb +153 -93
  83. data/spec/helpers/inputs_helper_spec.rb +14 -0
  84. data/spec/i18n_spec.rb +11 -0
  85. data/spec/inputs/boolean_input_spec.rb +31 -2
  86. data/spec/inputs/check_boxes_input_spec.rb +29 -1
  87. data/spec/inputs/date_input_spec.rb +95 -0
  88. data/spec/inputs/datetime_input_spec.rb +49 -0
  89. data/spec/inputs/email_input_spec.rb +28 -0
  90. data/spec/inputs/file_input_spec.rb +28 -0
  91. data/spec/inputs/hidden_input_spec.rb +28 -0
  92. data/spec/inputs/include_blank_spec.rb +53 -45
  93. data/spec/inputs/number_input_spec.rb +34 -4
  94. data/spec/inputs/password_input_spec.rb +28 -0
  95. data/spec/inputs/phone_input_spec.rb +28 -0
  96. data/spec/inputs/placeholder_spec.rb +10 -10
  97. data/spec/inputs/radio_input_spec.rb +51 -6
  98. data/spec/inputs/range_input_spec.rb +30 -2
  99. data/spec/inputs/search_input_spec.rb +27 -0
  100. data/spec/inputs/select_input_spec.rb +52 -6
  101. data/spec/inputs/string_input_spec.rb +28 -0
  102. data/spec/inputs/text_input_spec.rb +27 -0
  103. data/spec/inputs/time_input_spec.rb +67 -1
  104. data/spec/inputs/time_zone_input_spec.rb +28 -0
  105. data/spec/inputs/url_input_spec.rb +28 -0
  106. data/spec/inputs/with_options_spec.rb +43 -0
  107. data/spec/spec_helper.rb +22 -6
  108. data/spec/support/custom_macros.rb +6 -134
  109. data/spec/support/test_environment.rb +0 -1
  110. metadata +104 -17
  111. data/lib/formtastic/helpers/semantic_form_helper.rb +0 -11
  112. data/lib/formtastic/inputs/numeric_input.rb +0 -21
  113. data/lib/formtastic/railtie.rb +0 -12
  114. data/lib/formtastic/semantic_form_builder.rb +0 -11
  115. data/spec/builder/errors_spec.rb +0 -203
  116. data/spec/inputs/numeric_input_spec.rb +0 -41
@@ -56,62 +56,8 @@ module Formtastic
56
56
  end
57
57
  end
58
58
 
59
- # Generates error messages for the given method, used for displaying errors right near the
60
- # field for data entry. Uses the `:inline_errors` config to determin the right presentation,
61
- # which may be an ordered list, a paragraph sentence containing all errors, or a paragraph
62
- # containing just the first error. If configred to `:none`, no error is shown.
63
- #
64
- # See the `:inline_errors` config documentation for more details.
65
- #
66
- # This method is mostly used internally, but can be used in your forms when creating your own
67
- # custom inputs, so it's been made public and aliased to `errors_on`.
68
- #
69
- # @example
70
- # <%= semantic_form_for @post do |f| %>
71
- # <li class='my-custom-text-input'>
72
- # <%= f.label(:body) %>
73
- # <%= f.text_field(:body) %>
74
- # <%= f.errors_on(:body) %>
75
- # </li>
76
- # <% end %>
77
- #
78
- # @deprecated See the README for the currently supported approach to custom inputs.
79
- def inline_errors_for(method, options = {})
80
- ActiveSupport::Deprecation.warn('inline_errors_for and errors_on are deprecated and will be removed on or after version 2.1', caller)
81
- if render_inline_errors?
82
- errors = error_keys(method, options).map{|x| @object.errors[x] }.flatten.compact.uniq
83
- send(:"error_#{inline_errors}", [*errors], options) if errors.any?
84
- else
85
- nil
86
- end
87
- end
88
- alias :errors_on :inline_errors_for
89
-
90
-
91
59
  protected
92
60
 
93
- # @deprecated This should be removed with inline_errors_for in 2.1
94
- def error_sentence(errors, options = {})
95
- error_class = options[:error_class] || default_inline_error_class
96
- template.content_tag(:p, Formtastic::Util.html_safe(errors.to_sentence.untaint), :class => error_class)
97
- end
98
-
99
- # @deprecated This should be removed with inline_errors_for in 2.1
100
- def error_list(errors, options = {})
101
- error_class = options[:error_class] || default_error_list_class
102
- list_elements = []
103
- errors.each do |error|
104
- list_elements << template.content_tag(:li, Formtastic::Util.html_safe(error.untaint))
105
- end
106
- template.content_tag(:ul, Formtastic::Util.html_safe(list_elements.join("\n")), :class => error_class)
107
- end
108
-
109
- # @deprecated This should be removed with inline_errors_for in 2.1
110
- def error_first(errors, options = {})
111
- error_class = options[:error_class] || default_inline_error_class
112
- template.content_tag(:p, Formtastic::Util.html_safe(errors.first.untaint), :class => error_class)
113
- end
114
-
115
61
  def error_keys(method, options)
116
62
  @methods_for_error ||= {}
117
63
  @methods_for_error[method] ||= begin
@@ -25,10 +25,6 @@ module Formtastic
25
25
  contents = args.last.is_a?(::Hash) ? '' : args.pop.flatten
26
26
  html_options = args.extract_options!
27
27
 
28
- legend = (html_options[:name] || '').to_s
29
- legend %= parent_child_index(html_options[:parent]) if html_options[:parent]
30
- legend = template.content_tag(:legend, template.content_tag(:span, Formtastic::Util.html_safe(legend))) unless legend.blank?
31
-
32
28
  if block_given?
33
29
  contents = if template.respond_to?(:is_haml?) && template.is_haml?
34
30
  template.capture_haml(&block)
@@ -39,6 +35,8 @@ module Formtastic
39
35
 
40
36
  # Ruby 1.9: String#to_s behavior changed, need to make an explicit join.
41
37
  contents = contents.join if contents.respond_to?(:join)
38
+
39
+ legend = field_set_legend(html_options)
42
40
  fieldset = template.content_tag(:fieldset,
43
41
  Formtastic::Util.html_safe(legend) << template.content_tag(:ol, Formtastic::Util.html_safe(contents)),
44
42
  html_options.except(:builder, :parent, :name)
@@ -47,6 +45,13 @@ module Formtastic
47
45
  fieldset
48
46
  end
49
47
 
48
+ def field_set_legend(html_options)
49
+ legend = (html_options[:name] || '').to_s
50
+ legend %= parent_child_index(html_options[:parent]) if html_options[:parent]
51
+ legend = template.content_tag(:legend, template.content_tag(:span, Formtastic::Util.html_safe(legend))) unless legend.blank?
52
+ legend
53
+ end
54
+
50
55
  # Gets the nested_child_index value from the parent builder. It returns a hash with each
51
56
  # association that the parent builds.
52
57
  def parent_child_index(parent) #:nodoc:
@@ -72,4 +77,4 @@ module Formtastic
72
77
 
73
78
  end
74
79
  end
75
- end
80
+ end
@@ -144,7 +144,7 @@ module Formtastic
144
144
  options[:builder] ||= @@builder
145
145
  options[:html] ||= {}
146
146
  options[:html][:novalidate] = !@@builder.perform_browser_validations unless options[:html].key?(:novalidate)
147
- @@builder.custom_namespace = options[:namespace].to_s
147
+ @@builder.custom_namespace = options.delete(:namespace).to_s
148
148
 
149
149
  singularizer = defined?(ActiveModel::Naming.singular) ? ActiveModel::Naming.method(:singular) : ActionController::RecordIdentifier.method(:singular_class_name)
150
150
 
@@ -169,7 +169,7 @@ module Formtastic
169
169
  def semantic_fields_for(record_name, record_object = nil, options = {}, &block)
170
170
  options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
171
171
  options[:builder] ||= @@builder
172
- @@builder.custom_namespace = options[:namespace].to_s # TODO needed?
172
+ @@builder.custom_namespace = options.delete(:namespace).to_s # TODO needed?
173
173
 
174
174
  with_custom_field_error_proc do
175
175
  self.fields_for(record_name, record_object, options, &block)
@@ -140,15 +140,9 @@ module Formtastic
140
140
  # @option options :member_label [Symbol, Proc, Method]
141
141
  # Override the method called on each object in the `:collection` for use as the `<label>` content (`:check_boxes` & `:radio` inputs) or `<option>` content (`:select` inputs)
142
142
  #
143
- # @option options :label_method [Symbol, Proc, Method]
144
- # Deprecated, renamed to :member_label
145
- #
146
143
  # @option options :member_value [Symbol, Proc, Method]
147
144
  # Override the method called on each object in the `:collection` for use as the `value` attribute in the `<input>` (`:check_boxes` & `:radio` inputs) or `<option>` (`:select` inputs)
148
145
  #
149
- # @option options :value_method [Symbol, Proc, Method]
150
- # Deprecated, renamed to :member_value
151
- #
152
146
  # @option options :hint_class [String]
153
147
  # Override the `class` attribute applied to the `<p>` tag used when a `:hint` is rendered for an input
154
148
  #
@@ -164,9 +158,6 @@ module Formtastic
164
158
  # @option options :find_options [Symbol]
165
159
  # TODO will probably be deprecated
166
160
  #
167
- # @option options :group_label_method [Symbol]
168
- # Deprecated, use `:group_label`
169
- #
170
161
  # @option options :group_label [Symbol]
171
162
  # TODO will probably be deprecated
172
163
  #
@@ -177,7 +168,7 @@ module Formtastic
177
168
  # Specify the text in the first ('blank') `:select` input `<option>` to prompt a user to make a selection (implicitly sets `:include_blank` to `true`)
178
169
  #
179
170
  # @todo Can we kill `:hint_class` & `:error_class`? What's the use case for input-by-input? Shift to config or burn!
180
- # @todo Can we kill `:group_by` & `:group_label`/`:group_label_method`? Should be done with :collection => grouped_options_for_select(...)
171
+ # @todo Can we kill `:group_by` & `:group_label`? Should be done with :collection => grouped_options_for_select(...)
181
172
  # @todo Can we kill `:find_options`? Should be done with MyModel.some_scope.where(...).order(...).whatever_scope
182
173
  # @todo Can we kill `:label`, `:hint` & `:prompt`? All strings could be shifted to i18n!
183
174
  #
@@ -300,7 +300,7 @@ module Formtastic
300
300
  end
301
301
 
302
302
  out = template.content_tag(:li, out, :class => "input") if wrap_it
303
- @already_in_an_inputs_block = false
303
+ @already_in_an_inputs_block = wrap_it
304
304
  out
305
305
  end
306
306
 
@@ -351,7 +351,10 @@ module Formtastic
351
351
 
352
352
  # Collects content columns (non-relation columns) for the current form object class.
353
353
  def content_columns #:nodoc:
354
- model_name.constantize.content_columns.collect { |c| c.name.to_sym }.compact rescue []
354
+ # TODO: NameError is raised by Inflector.constantize. Consider checking if it exists instead.
355
+ begin klass = model_name.constantize; rescue NameError; return [] end
356
+ return [] unless klass.respond_to?(:content_columns)
357
+ klass.content_columns.collect { |c| c.name.to_sym }.compact
355
358
  end
356
359
 
357
360
  # Deals with :for option when it's supplied to inputs methods. Additional
@@ -397,4 +400,4 @@ module Formtastic
397
400
 
398
401
  end
399
402
  end
400
- end
403
+ end
@@ -8,10 +8,11 @@ module Formtastic
8
8
  DEFAULT_VALUES = YAML.load_file(File.expand_path("../../locale/en.yml", __FILE__))["en"]["formtastic"].freeze
9
9
  SCOPES = [
10
10
  '%{model}.%{nested_model}.%{action}.%{attribute}',
11
- '%{model}.%{action}.%{attribute}',
12
11
  '%{model}.%{nested_model}.%{attribute}',
13
- '%{model}.%{attribute}',
12
+ '%{nested_model}.%{action}.%{attribute}',
14
13
  '%{nested_model}.%{attribute}',
14
+ '%{model}.%{action}.%{attribute}',
15
+ '%{model}.%{attribute}',
15
16
  '%{attribute}'
16
17
  ]
17
18
 
@@ -12,11 +12,12 @@ module Formtastic
12
12
  @method = method
13
13
  @options = options.dup
14
14
 
15
- warn_and_correct_option!(:label_method, :member_label)
16
- warn_and_correct_option!(:value_method, :member_value)
17
- warn_and_correct_option!(:group_label_method, :group_label)
15
+ removed_option!(:label_method)
16
+ removed_option!(:value_method)
17
+ removed_option!(:group_label_method)
18
18
  end
19
19
 
20
+ # Usefull for deprecating options.
20
21
  def warn_and_correct_option!(old_option_name, new_option_name)
21
22
  if options.key?(old_option_name)
22
23
  ::ActiveSupport::Deprecation.warn("The :#{old_option_name} option is deprecated in favour of :#{new_option_name} and will be removed from Formtastic after 2.0")
@@ -24,6 +25,11 @@ module Formtastic
24
25
  end
25
26
  end
26
27
 
28
+ # Usefull for raising an error on previously supported option.
29
+ def removed_option!(old_option_name)
30
+ raise ArgumentError, ":#{old_option_name} is no longer available" if options.key?(old_option_name)
31
+ end
32
+
27
33
  extend ActiveSupport::Autoload
28
34
 
29
35
  autoload :Associations
@@ -37,7 +43,9 @@ module Formtastic
37
43
  autoload :Html
38
44
  autoload :Labelling
39
45
  autoload :Naming
46
+ autoload :Numeric
40
47
  autoload :Options
48
+ autoload :Placeholder
41
49
  autoload :Stringish
42
50
  autoload :Timeish
43
51
  autoload :Validations
@@ -44,7 +44,11 @@ module Formtastic
44
44
  end
45
45
 
46
46
  def choice_label(choice)
47
- choice.is_a?(Array) ? choice.first : choice
47
+ if choice.is_a?(Array)
48
+ choice.first
49
+ else
50
+ choice
51
+ end.to_s
48
52
  end
49
53
 
50
54
  def choice_value(choice)
@@ -71,6 +75,7 @@ module Formtastic
71
75
  [
72
76
  builder.custom_namespace,
73
77
  sanitized_object_name,
78
+ builder.options[:index],
74
79
  association_primary_key || method,
75
80
  choice_html_safe_value(choice)
76
81
  ].compact.reject { |i| i.blank? }.join("_")
@@ -4,14 +4,26 @@ module Formtastic
4
4
  module Collections
5
5
 
6
6
  def label_method
7
- label_and_value_method(raw_collection).first
7
+ @label_method ||= (label_method_from_options || label_and_value_method.first)
8
+ end
9
+
10
+ def label_method_from_options
11
+ options[:member_label]
8
12
  end
9
13
 
10
14
  def value_method
11
- label_and_value_method(raw_collection).last
15
+ @value_method ||= (value_method_from_options || label_and_value_method.last)
16
+ end
17
+
18
+ def value_method_from_options
19
+ options[:member_value]
12
20
  end
13
21
 
14
- def label_and_value_method(_collection, grouped=false)
22
+ def label_and_value_method
23
+ @label_and_value_method ||= label_and_value_method_from_collection(raw_collection)
24
+ end
25
+
26
+ def label_and_value_method_from_collection(_collection)
15
27
  sample = _collection.first || _collection.last
16
28
 
17
29
  case sample
@@ -19,13 +31,13 @@ module Formtastic
19
31
  label, value = :first, :last
20
32
  when Integer
21
33
  label, value = :to_s, :to_i
22
- when String, NilClass
34
+ when Symbol, String, NilClass
23
35
  label, value = :to_s, :to_s
24
36
  end
25
37
 
26
38
  # Order of preference: user supplied method, class defaults, auto-detect
27
- label = (grouped ? options[:grouped_label_method] : options[:member_label]) || label || builder.collection_label_methods.find { |m| sample.respond_to?(m) }
28
- value = (grouped ? options[:grouped_value_method] : options[:member_value]) || value || builder.collection_value_methods.find { |m| sample.respond_to?(m) }
39
+ label ||= builder.collection_label_methods.find { |m| sample.respond_to?(m) }
40
+ value ||= builder.collection_value_methods.find { |m| sample.respond_to?(m) }
29
41
 
30
42
  [label, value]
31
43
  end
@@ -40,7 +52,7 @@ module Formtastic
40
52
 
41
53
  # Return if we have an Array of strings, fixnums or arrays
42
54
  return raw_collection if (raw_collection.instance_of?(Array) || raw_collection.instance_of?(Range)) &&
43
- [Array, Fixnum, String, Symbol].include?(raw_collection.first.class) &&
55
+ [Array, Fixnum, String].include?(raw_collection.first.class) &&
44
56
  !(options.include?(:member_label) || options.include?(:member_value))
45
57
 
46
58
  raw_collection.map { |o| [send_or_call(label_method, o), send_or_call(value_method, o)] }
@@ -48,24 +60,35 @@ module Formtastic
48
60
 
49
61
  def collection_from_options
50
62
  items = options[:collection]
51
- items = items.to_a if items.is_a?(Hash)
52
- items
63
+ case items
64
+ when Hash
65
+ items.to_a
66
+ when Range
67
+ items.to_a.collect{ |c| [c.to_s, c] }
68
+ else
69
+ items
70
+ end
53
71
  end
54
72
 
55
73
  def collection_from_association
56
74
  if reflection
57
- raise PolymorphicInputWithoutCollectionError.new("A collection must be supplied for #{method} input. Collections cannot be guessed for polymorphic associations.") if reflection.options && reflection.options[:polymorphic] == true
75
+ if reflection.respond_to?(:options)
76
+ raise PolymorphicInputWithoutCollectionError.new(
77
+ "A collection must be supplied for #{method} input. Collections cannot be guessed for polymorphic associations."
78
+ ) if reflection.options[:polymorphic] == true
79
+ end
58
80
 
59
81
  find_options_from_options = options[:find_options] || {}
60
82
  conditions_from_options = find_options_from_options[:conditions] || {}
61
- conditions_from_reflection = reflection.options && reflection.options[:conditions] || {}
83
+ conditions_from_reflection = (reflection.respond_to?(:options) && reflection.options[:conditions]) || {}
62
84
  conditions_from_reflection = conditions_from_reflection.call if conditions_from_reflection.is_a?(Proc)
63
85
 
86
+ scope_conditions = conditions_from_reflection.empty? ? nil : {:conditions => conditions_from_reflection}
64
87
  if conditions_from_options.any?
65
- reflection.klass.scoped(:conditions => conditions_from_reflection).where(conditions_from_options)
88
+ reflection.klass.scoped(scope_conditions).where(conditions_from_options)
66
89
  else
67
90
  find_options_from_options.merge!(:include => group_by) if self.respond_to?(:group_by) && group_by
68
- reflection.klass.scoped(:conditions => conditions_from_reflection).where(find_options_from_options)
91
+ reflection.klass.scoped(scope_conditions).where(find_options_from_options)
69
92
  end
70
93
  end
71
94
  end
@@ -20,7 +20,7 @@ module Formtastic
20
20
  end
21
21
 
22
22
  def group_label_method_from_grouped_collection
23
- label_and_value_method(raw_grouped_collection, true).first
23
+ label_and_value_method_from_collection(raw_grouped_collection).first
24
24
  end
25
25
 
26
26
  def group_association
@@ -0,0 +1,50 @@
1
+ module Formtastic
2
+ module Inputs
3
+ module Base
4
+ module Numeric
5
+ def input_html_options
6
+ defaults = super
7
+
8
+ # override rails default size - not valid on numeric inputs
9
+ #@todo document/spec
10
+ defaults[:size] = nil
11
+
12
+ if in_option
13
+ defaults[:min] = in_option.to_a.min
14
+ defaults[:max] = in_option.to_a.max
15
+ else
16
+ defaults[:min] ||= min_option
17
+ defaults[:max] ||= max_option
18
+ end
19
+ defaults[:step] ||= step_option
20
+ defaults
21
+ end
22
+
23
+ def step_option
24
+ return options[:step] if options.key?(:step)
25
+ validation_step
26
+ end
27
+
28
+ def min_option
29
+ return options[:min] if options.key?(:min)
30
+ validation_min
31
+ end
32
+
33
+ def max_option
34
+ return options[:max] if options.key?(:max)
35
+ validation_max
36
+ end
37
+
38
+ def in_option
39
+ options[:in]
40
+ end
41
+
42
+ def wrapper_html_options
43
+ new_class = [super[:class], "numeric", "stringish"].compact.join(" ")
44
+ super.merge(:class => new_class)
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -8,7 +8,7 @@ module Formtastic
8
8
  end
9
9
 
10
10
  def formtastic_options
11
- [:priority_countries, :priority_zones, :value_method, :label_method, :member_label, :member_value, :collection, :required, :label, :as, :hint, :input_html, :label_html, :value_as_class, :find_options, :class]
11
+ [:priority_countries, :priority_zones, :member_label, :member_value, :collection, :required, :label, :as, :hint, :input_html, :label_html, :value_as_class, :find_options, :class]
12
12
  end
13
13
 
14
14
  end
@@ -0,0 +1,17 @@
1
+ module Formtastic
2
+ module Inputs
3
+ module Base
4
+ module Placeholder
5
+
6
+ def input_html_options
7
+ {:placeholder => placeholder_text}.merge(super)
8
+ end
9
+
10
+ def placeholder_text
11
+ localized_string(method, options[:placeholder], :placeholder)
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,7 +2,7 @@ module Formtastic
2
2
  module Inputs
3
3
  module Base
4
4
  module Stringish
5
-
5
+
6
6
  # @abstract Override this method in your input class to describe how the input should render itself.
7
7
  def to_html
8
8
  input_wrapping do
@@ -15,15 +15,10 @@ module Formtastic
15
15
  def input_html_options
16
16
  {
17
17
  :maxlength => options[:input_html].try(:[], :maxlength) || limit,
18
- :size => builder.default_text_field_size,
19
- :placeholder => placeholder_text
18
+ :size => builder.default_text_field_size
20
19
  }.merge(super)
21
20
  end
22
21
 
23
- def placeholder_text
24
- localized_string(method, options[:placeholder], :placeholder)
25
- end
26
-
27
22
  def wrapper_html_options
28
23
  new_class = [super[:class], "stringish"].compact.join(" ")
29
24
  super.merge(:class => new_class)