formtastic 2.0.2 → 2.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -1
- data/Appraisals +11 -0
- data/CHANGELOG +2 -2
- data/Gemfile +0 -2
- data/README.textile +183 -151
- data/Rakefile +9 -5
- data/app/assets/stylesheets/formtastic.css +16 -3
- data/formtastic.gemspec +6 -2
- data/gemfiles/rails-3.0.gemfile +7 -0
- data/gemfiles/rails-3.1.gemfile +7 -0
- data/gemfiles/rails-3.2.gemfile +7 -0
- data/lib/formtastic.rb +10 -2
- data/lib/formtastic/actions.rb +11 -0
- data/lib/formtastic/actions/base.rb +156 -0
- data/lib/formtastic/actions/button_action.rb +72 -0
- data/lib/formtastic/actions/buttonish.rb +17 -0
- data/lib/formtastic/actions/input_action.rb +68 -0
- data/lib/formtastic/actions/link_action.rb +87 -0
- data/lib/formtastic/engine.rb +5 -1
- data/lib/formtastic/form_builder.rb +3 -0
- data/lib/formtastic/helpers.rb +2 -1
- data/lib/formtastic/helpers/action_helper.rb +109 -0
- data/lib/formtastic/helpers/actions_helper.rb +168 -0
- data/lib/formtastic/helpers/buttons_helper.rb +22 -9
- data/lib/formtastic/helpers/errors_helper.rb +0 -54
- data/lib/formtastic/helpers/fieldset_wrapper.rb +10 -5
- data/lib/formtastic/helpers/form_helper.rb +2 -2
- data/lib/formtastic/helpers/input_helper.rb +1 -10
- data/lib/formtastic/helpers/inputs_helper.rb +6 -3
- data/lib/formtastic/i18n.rb +3 -2
- data/lib/formtastic/inputs/base.rb +11 -3
- data/lib/formtastic/inputs/base/choices.rb +6 -1
- data/lib/formtastic/inputs/base/collections.rb +36 -13
- data/lib/formtastic/inputs/base/grouped_collections.rb +1 -1
- data/lib/formtastic/inputs/base/numeric.rb +50 -0
- data/lib/formtastic/inputs/base/options.rb +1 -1
- data/lib/formtastic/inputs/base/placeholder.rb +17 -0
- data/lib/formtastic/inputs/base/stringish.rb +2 -7
- data/lib/formtastic/inputs/base/timeish.rb +21 -5
- data/lib/formtastic/inputs/base/validations.rb +1 -1
- data/lib/formtastic/inputs/base/wrapping.rb +10 -3
- data/lib/formtastic/inputs/boolean_input.rb +10 -2
- data/lib/formtastic/inputs/check_boxes_input.rb +18 -9
- data/lib/formtastic/inputs/country_input.rb +2 -2
- data/lib/formtastic/inputs/date_input.rb +19 -1
- data/lib/formtastic/inputs/datetime_input.rb +1 -1
- data/lib/formtastic/inputs/email_input.rb +2 -1
- data/lib/formtastic/inputs/file_input.rb +1 -1
- data/lib/formtastic/inputs/hidden_input.rb +1 -1
- data/lib/formtastic/inputs/number_input.rb +6 -36
- data/lib/formtastic/inputs/password_input.rb +2 -1
- data/lib/formtastic/inputs/phone_input.rb +3 -2
- data/lib/formtastic/inputs/radio_input.rb +1 -1
- data/lib/formtastic/inputs/range_input.rb +8 -32
- data/lib/formtastic/inputs/search_input.rb +2 -1
- data/lib/formtastic/inputs/select_input.rb +56 -28
- data/lib/formtastic/inputs/string_input.rb +3 -1
- data/lib/formtastic/inputs/text_input.rb +5 -4
- data/lib/formtastic/inputs/time_input.rb +4 -8
- data/lib/formtastic/inputs/time_zone_input.rb +1 -1
- data/lib/formtastic/inputs/url_input.rb +2 -1
- data/lib/formtastic/localized_string.rb +6 -94
- data/lib/formtastic/localizer.rb +110 -0
- data/lib/formtastic/version.rb +1 -1
- data/lib/generators/formtastic/form/form_generator.rb +105 -0
- data/lib/generators/templates/_form.html.erb +2 -2
- data/lib/generators/templates/_form.html.haml +4 -4
- data/lib/generators/templates/_form.html.slim +2 -2
- data/lib/generators/templates/formtastic.rb +4 -0
- data/lib/locale/en.yml +2 -0
- data/sample/basic_inputs.html +22 -0
- data/spec/actions/button_action_spec.rb +63 -0
- data/spec/actions/generic_action_spec.rb +484 -0
- data/spec/actions/input_action_spec.rb +59 -0
- data/spec/actions/link_action_spec.rb +92 -0
- data/spec/builder/semantic_fields_for_spec.rb +14 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +118 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
- data/spec/helpers/action_helper_spec.rb +365 -0
- data/spec/helpers/actions_helper_spec.rb +143 -0
- data/spec/helpers/buttons_helper_spec.rb +39 -23
- data/spec/helpers/commit_button_helper_spec.rb +153 -93
- data/spec/helpers/inputs_helper_spec.rb +14 -0
- data/spec/i18n_spec.rb +11 -0
- data/spec/inputs/boolean_input_spec.rb +31 -2
- data/spec/inputs/check_boxes_input_spec.rb +29 -1
- data/spec/inputs/date_input_spec.rb +95 -0
- data/spec/inputs/datetime_input_spec.rb +49 -0
- data/spec/inputs/email_input_spec.rb +28 -0
- data/spec/inputs/file_input_spec.rb +28 -0
- data/spec/inputs/hidden_input_spec.rb +28 -0
- data/spec/inputs/include_blank_spec.rb +53 -45
- data/spec/inputs/number_input_spec.rb +34 -4
- data/spec/inputs/password_input_spec.rb +28 -0
- data/spec/inputs/phone_input_spec.rb +28 -0
- data/spec/inputs/placeholder_spec.rb +10 -10
- data/spec/inputs/radio_input_spec.rb +51 -6
- data/spec/inputs/range_input_spec.rb +30 -2
- data/spec/inputs/search_input_spec.rb +27 -0
- data/spec/inputs/select_input_spec.rb +52 -6
- data/spec/inputs/string_input_spec.rb +28 -0
- data/spec/inputs/text_input_spec.rb +27 -0
- data/spec/inputs/time_input_spec.rb +67 -1
- data/spec/inputs/time_zone_input_spec.rb +28 -0
- data/spec/inputs/url_input_spec.rb +28 -0
- data/spec/inputs/with_options_spec.rb +43 -0
- data/spec/spec_helper.rb +22 -6
- data/spec/support/custom_macros.rb +6 -134
- data/spec/support/test_environment.rb +0 -1
- metadata +104 -17
- data/lib/formtastic/helpers/semantic_form_helper.rb +0 -11
- data/lib/formtastic/inputs/numeric_input.rb +0 -21
- data/lib/formtastic/railtie.rb +0 -12
- data/lib/formtastic/semantic_form_builder.rb +0 -11
- data/spec/builder/errors_spec.rb +0 -203
- 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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
data/lib/formtastic/i18n.rb
CHANGED
|
@@ -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
|
-
'%{
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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)
|
|
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
|
|
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
|
|
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
|
|
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
|
|
28
|
-
value
|
|
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
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
91
|
+
reflection.klass.scoped(scope_conditions).where(find_options_from_options)
|
|
69
92
|
end
|
|
70
93
|
end
|
|
71
94
|
end
|
|
@@ -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, :
|
|
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)
|