formtastic 2.3.0.rc2 → 2.3.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.travis.yml +27 -1
  2. data/Appraisals +5 -0
  3. data/CHANGELOG +1 -0
  4. data/README.textile +19 -26
  5. data/formtastic.gemspec +4 -3
  6. data/gemfiles/rails_3.0.gemfile +1 -1
  7. data/gemfiles/rails_3.1.gemfile +1 -1
  8. data/gemfiles/rails_3.2.gemfile +1 -1
  9. data/gemfiles/rails_4.0.4.gemfile +7 -0
  10. data/gemfiles/rails_4.gemfile +1 -1
  11. data/lib/formtastic/form_builder.rb +9 -1
  12. data/lib/formtastic/helpers/form_helper.rb +11 -6
  13. data/lib/formtastic/helpers/inputs_helper.rb +6 -1
  14. data/lib/formtastic/inputs/base/collections.rb +1 -1
  15. data/lib/formtastic/inputs/base/validations.rb +1 -1
  16. data/lib/formtastic/inputs/boolean_input.rb +4 -14
  17. data/lib/formtastic/inputs/check_boxes_input.rb +7 -1
  18. data/lib/formtastic/inputs/radio_input.rb +2 -0
  19. data/lib/formtastic/util.rb +13 -1
  20. data/lib/formtastic/version.rb +1 -1
  21. data/lib/generators/templates/_form.html.slim +2 -2
  22. data/lib/generators/templates/formtastic.rb +15 -1
  23. data/spec/actions/generic_action_spec.rb +3 -3
  24. data/spec/builder/custom_builder_spec.rb +7 -7
  25. data/spec/builder/semantic_fields_for_spec.rb +8 -8
  26. data/spec/generators/formtastic/form/form_generator_spec.rb +6 -6
  27. data/spec/helpers/action_helper_spec.rb +11 -11
  28. data/spec/helpers/form_helper_spec.rb +22 -11
  29. data/spec/helpers/input_helper_spec.rb +44 -44
  30. data/spec/helpers/inputs_helper_spec.rb +64 -31
  31. data/spec/helpers/semantic_errors_helper_spec.rb +12 -12
  32. data/spec/i18n_spec.rb +5 -5
  33. data/spec/inputs/boolean_input_spec.rb +6 -5
  34. data/spec/inputs/check_boxes_input_spec.rb +27 -9
  35. data/spec/inputs/country_input_spec.rb +5 -5
  36. data/spec/inputs/custom_input_spec.rb +1 -1
  37. data/spec/inputs/date_picker_input_spec.rb +4 -4
  38. data/spec/inputs/datetime_picker_input_spec.rb +4 -4
  39. data/spec/inputs/hidden_input_spec.rb +3 -3
  40. data/spec/inputs/include_blank_spec.rb +2 -2
  41. data/spec/inputs/number_input_spec.rb +36 -36
  42. data/spec/inputs/radio_input_spec.rb +23 -5
  43. data/spec/inputs/range_input_spec.rb +19 -19
  44. data/spec/inputs/select_input_spec.rb +40 -20
  45. data/spec/inputs/string_input_spec.rb +2 -2
  46. data/spec/inputs/time_picker_input_spec.rb +4 -4
  47. data/spec/localizer_spec.rb +1 -1
  48. data/spec/spec_helper.rb +203 -188
  49. data/spec/support/custom_macros.rb +8 -8
  50. metadata +15 -13
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
- before_install:
1
+ before_install:
2
2
  - gem update --system
3
3
  - gem update bundler
4
4
  rvm:
@@ -6,6 +6,8 @@ rvm:
6
6
  - ree
7
7
  - 1.9.2
8
8
  - 1.9.3
9
+ - 2.0.0
10
+ - 2.1.0
9
11
  gemfile:
10
12
  - gemfiles/rails_3.0.gemfile
11
13
  - gemfiles/rails_3.1.gemfile
@@ -21,6 +23,24 @@ matrix:
21
23
  - rvm: 2.0.0
22
24
  gemfile: gemfiles/rails_4.gemfile
23
25
  env: DEFER_GC=false RAILS_EDGE=true
26
+ - rvm: 2.1.0
27
+ gemfile: gemfiles/rails_4.gemfile
28
+ env: DEFER_GC=false RAILS_EDGE=true
29
+ - rvm: 1.9.3
30
+ gemfile: gemfiles/rails_4.0.4.gemfile
31
+ env: DEFER_GC=false RAILS_EDGE=true
32
+ - rvm: 2.0.0
33
+ gemfile: gemfiles/rails_4.0.4.gemfile
34
+ env: DEFER_GC=false RAILS_EDGE=true
35
+ - rvm: 1.9.3
36
+ gemfile: gemfiles/rails_edge.gemfile
37
+ env: DEFER_GC=false RAILS_EDGE=true
38
+ - rvm: 2.0.0
39
+ gemfile: gemfiles/rails_edge.gemfile
40
+ env: DEFER_GC=false RAILS_EDGE=true
41
+ - rvm: 2.1.0
42
+ gemfile: gemfiles/rails_edge.gemfile
43
+ env: DEFER_GC=false RAILS_EDGE=true
24
44
  allow_failures:
25
45
  - rvm: 1.9.3
26
46
  gemfile: gemfiles/rails_edge.gemfile
@@ -28,3 +48,9 @@ matrix:
28
48
  - rvm: 2.0.0
29
49
  gemfile: gemfiles/rails_edge.gemfile
30
50
  env: DEFER_GC=false RAILS_EDGE=true
51
+ - rvm: 2.1.0
52
+ gemfile: gemfiles/rails_4.gemfile
53
+ env: DEFER_GC=false RAILS_EDGE=true
54
+ - rvm: 2.1.0
55
+ gemfile: gemfiles/rails_edge.gemfile
56
+ env: DEFER_GC=false RAILS_EDGE=true
data/Appraisals CHANGED
@@ -14,6 +14,11 @@ appraise 'rails-4' do
14
14
  gem 'rails', '~> 4.0.0'
15
15
  end
16
16
 
17
+ # Special case for a change in I18n
18
+ appraise 'rails-4.0.4' do
19
+ gem 'rails', '4.0.4'
20
+ end
21
+
17
22
  if ENV["RAILS_EDGE"] == "true"
18
23
  appraise 'rails-edge' do
19
24
  gem 'rails', :git => 'git://github.com/rails/rails.git'
data/CHANGELOG CHANGED
@@ -1,6 +1,7 @@
1
1
  2.3.0.rc2
2
2
 
3
3
  * deprecate support for Rails < 3.2
4
+ * avoid clobbering `ActionView::Base.field_error_proc=` by using a custom class attribute: `Formtastic::Helpers::FormHelper.formtastic_field_error_proc=`.
4
5
 
5
6
  2.3.0.rc
6
7
 
data/README.textile CHANGED
@@ -1,8 +1,12 @@
1
1
  h1. Formtastic
2
2
 
3
- Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications.
3
+ !https://travis-ci.org/justinfrench/formtastic.png?branch=master!:https://travis-ci.org/justinfrench/formtastic
4
+ !http://inch-pages.github.io/github/justinfrench/formtastic.png!:http://inch-pages.github.io/github/justinfrench/formtastic
5
+ !https://codeclimate.com/github/justinfrench/formtastic.png!:https://codeclimate.com/github/justinfrench/formtastic
6
+ !https://badge.fury.io/rb/formtastic.png!:http://badge.fury.io/rb/formtastic
7
+ !https://gemnasium.com/justinfrench/formtastic.png!:https://gemnasium.com/justinfrench/formtastic
4
8
 
5
- <a href='http://www.pledgie.com/campaigns/2178'><img alt='Click here to lend your support to: formtastic and make a donation at www.pledgie.com !' src='http://pledgie.com/campaigns/2178.png?skin_name=chrome' border='0' /></a>
9
+ Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications.
6
10
 
7
11
 
8
12
  h2. Documentation & Support
@@ -20,7 +24,7 @@ h2. Compatibility
20
24
  * Formtastic 2.3 is Rails 3 and Rails 4 compatible (Rails < 3.2 is deprecated)
21
25
  * Formtastic 2.1 & 2.2 is Rails 3 and Rails 4 compatible
22
26
  * Formtastic, much like Rails, is very ActiveRecord-centric. Many are successfully using other ActiveModel-like ORMs and objects (DataMapper, MongoMapper, Mongoid, Authlogic, Devise...) but we're not guaranteeing full compatibility at this stage. Patches are welcome!
23
-
27
+
24
28
 
25
29
  h2. The Story
26
30
 
@@ -95,7 +99,7 @@ Simply add Formtastic to your Gemfile and bundle it up:
95
99
  Run the installation generator:
96
100
 
97
101
  <pre>
98
- $ rails generate formtastic:install
102
+ $ rails generate formtastic:install
99
103
  </pre>
100
104
 
101
105
 
@@ -106,7 +110,7 @@ A proof-of-concept set of stylesheets are provided which you can include in your
106
110
  h3. Stylesheet usage in Rails < 3.1:
107
111
 
108
112
  <pre>
109
- $ rails generate formtastic:install
113
+ $ rails generate formtastic:install
110
114
  </pre>
111
115
 
112
116
  <pre>
@@ -131,7 +135,7 @@ Conditional stylesheets need to be compiled separately to prevent them being bun
131
135
  <pre>
132
136
  # app/assets/stylesheets/ie6.css
133
137
  *= require formtastic_ie6
134
-
138
+
135
139
  # app/assets/stylesheets/ie7.css
136
140
  *= require formtastic_ie7
137
141
  </pre>
@@ -145,7 +149,7 @@ Conditional stylesheets need to be compiled separately to prevent them being bun
145
149
 
146
150
  <pre>
147
151
  # config/environments/production.rb
148
- config.assets.precompile += %w( ie6.css ie7.css )
152
+ config.assets.precompile += %w( ie6.css ie7.css )
149
153
  </pre>
150
154
 
151
155
  h2. Usage
@@ -365,7 +369,7 @@ Formtastic decides which label to use in the following order:
365
369
  1. :label # :label => "Choose Title"
366
370
  2. Formtastic i18n # if either :label => true || i18n_lookups_by_default = true (see Internationalization)
367
371
  3. Activerecord i18n # if localization file found for the given attribute
368
- 4. label_str_method # if nothing provided this defaults to :humanize but can be set to a custom method
372
+ 4. label_str_method # if nothing provided this defaults to :humanize but can be set to a custom method
369
373
  </pre>
370
374
 
371
375
  h2. Internationalization (I18n)
@@ -398,7 +402,7 @@ Formtastic supports localized *labels*, *hints*, *legends*, *actions* using the
398
402
  Formtastic::FormBuilder.i18n_lookups_by_default = true
399
403
  </pre>
400
404
 
401
- *2. Add some cool label-translations/variants (@config/locale/en.yml@):*
405
+ *2. Add some label-translations/variants (@config/locales/en.yml@):*
402
406
 
403
407
  <pre>
404
408
  en:
@@ -593,39 +597,28 @@ To create a custom @DatePickerInput@ from scratch, put the following in @app/inp
593
597
 
594
598
  You can use your new input with @:as => :date_picker@.
595
599
 
596
- h3. Don't subclass Formtastic::FormBuilder anymore
597
-
598
- It was previously recommended in Formtastic 1.x to subclass Formtastic::FormBuilder to add your own inputs. This is no longer recommended in Formtastic 2, and will not work as expected.
599
-
600
-
601
- h2. Security
602
-
603
- By default, Formtastic escapes HTML entities in both labels and hints unless a string is marked as html_safe. If you are using an older rails version which doesn't know html_safe, or you want to globally turn this feature off, you can set the following in your initializer:
604
-
605
- Formtastic::FormBuilder.escape_html_entities_in_hints_and_labels = false
606
-
607
600
 
608
601
  h2. Dependencies
609
602
 
610
603
  There are none other than Rails itself, but...
611
604
 
612
- * If you want to use the @:country@ input, you'll need to install the "country-select plugin":https://github.com/chrislerum/country_select (or any other country_select plugin with the same API).
613
- * There are a bunch of development dependencies
605
+ * If you want to use the @:country@ input, you'll need to install the "country-select plugin":https://github.com/stefanpenner/country_select (or any other country_select plugin with the same API).
606
+ * There are a bunch of development dependencies if you plan to contribute to Formtastic
614
607
 
615
608
 
616
609
  h2. How to contribute
617
610
 
618
611
  * Fork the project on Github
619
612
  * Create a topic branch for your changes
620
- * Ensure that you provide test coverage for your changes
613
+ * Ensure that you provide *documentation* and *test coverage* for your changes (patches won't be accepted without)
621
614
  * Ensure that all tests pass (`bundle exec rake`)
622
- * Create a pull request on Github
615
+ * Create a pull request on Github (these are also a great place to start a conversation around a patch as early as possible)
623
616
 
624
617
 
625
618
  h2. Project Info
626
619
 
627
- Formtastic was created by "Justin French":http://www.justinfrench.com with contributions from around 150 awesome developers. Run @git shortlog -n -s@ to see the awesome.
620
+ Formtastic was created by "Justin French":http://www.justinfrench.com with contributions from around 180 awesome developers. Run @git shortlog -n -s@ to see the awesome.
628
621
 
629
622
  The project is hosted on Github: "http://github.com/justinfrench/formtastic":http://github.com/justinfrench/formtastic, where your contributions, forkings, comments, issues and feedback are greatly welcomed.
630
623
 
631
- Copyright (c) 2007-2012 Justin French, released under the MIT license.
624
+ Copyright (c) 2007-2014 Justin French, released under the MIT license.
data/formtastic.gemspec CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = %q{http://github.com/justinfrench/formtastic}
12
12
  s.summary = %q{A Rails form builder plugin/gem with semantically rich and accessible markup}
13
13
  s.description = %q{A Rails form builder plugin/gem with semantically rich and accessible markup}
14
+ s.license = 'MIT'
14
15
 
15
16
  s.files = `git ls-files`.split("\n")
16
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -26,7 +27,7 @@ Gem::Specification.new do |s|
26
27
  s.add_dependency(%q<actionpack>, [">= 3.0"])
27
28
 
28
29
  s.add_development_dependency(%q<nokogiri>, ["< 1.6.0"]) # 1.6 requires Ruby 1.9.2, drop in v3.0
29
- s.add_development_dependency(%q<rspec-rails>, ["~> 2.12.0"])
30
+ s.add_development_dependency(%q<rspec-rails>, ["~> 2.14.0"])
30
31
  s.add_development_dependency(%q<rspec_tag_matchers>, [">= 1.0.0"])
31
32
  s.add_development_dependency(%q<hpricot>, ["~> 0.8.3"])
32
33
  s.add_development_dependency(%q<BlueCloth>) # for YARD
@@ -34,7 +35,7 @@ Gem::Specification.new do |s|
34
35
  s.add_development_dependency(%q<colored>)
35
36
  s.add_development_dependency(%q<tzinfo>)
36
37
  s.add_development_dependency(%q<ammeter>, ["0.2.5"])
37
- s.add_development_dependency(%q<appraisal>)
38
- s.add_development_dependency(%q<rake>)
38
+ s.add_development_dependency(%q<appraisal>, ["1.0.0.beta3"])
39
+ s.add_development_dependency(%q<rake>, ["<= 10.1.1"]) # Anything higher requires Ruby 1.9, drop in v3.0
39
40
  s.add_development_dependency(%q<activemodel>)
40
41
  end
@@ -4,4 +4,4 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.0.0"
6
6
 
7
- gemspec :path=>"../"
7
+ gemspec :path=>".././"
@@ -4,4 +4,4 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.1.0"
6
6
 
7
- gemspec :path=>"../"
7
+ gemspec :path=>".././"
@@ -4,4 +4,4 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.2.0"
6
6
 
7
- gemspec :path=>"../"
7
+ gemspec :path=>".././"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "4.0.4"
6
+
7
+ gemspec :path=>".././"
@@ -4,4 +4,4 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 4.0.0"
6
6
 
7
- gemspec :path=>"../"
7
+ gemspec :path=>".././"
@@ -82,7 +82,15 @@ module Formtastic
82
82
  end
83
83
 
84
84
  def initialize(object_name, object, template, options, block=nil)
85
- super
85
+ # rails 3 supported passing in the block parameter to FormBuilder
86
+ # rails 4.0 deprecated the block parameter and does nothing with it
87
+ # rails 4.1 removes the parameter completely
88
+ if Util.rails3? || Util.rails4_0?
89
+ super
90
+ else # Must be rails4_1 or greater
91
+ super object_name, object, template, options
92
+ end
93
+
86
94
  if respond_to?('multipart=') && options.is_a?(Hash) && options[:html]
87
95
  self.multipart = options[:html][:multipart]
88
96
  end
@@ -58,11 +58,16 @@ module Formtastic
58
58
  @@default_form_class = 'formtastic'
59
59
  mattr_accessor :default_form_class
60
60
 
61
+ # Allows to set a custom proc to handle the class infered from the model's name. By default it
62
+ # will infer the name from the class name (eg. Post will be "post").
63
+ @@default_form_model_class_proc = proc { |model_class_name| model_class_name }
64
+ mattr_accessor :default_form_model_class_proc
65
+
61
66
  # Allows to set a custom field_error_proc wrapper. By default this wrapper
62
67
  # is disabled since `formtastic` already adds an error class to the LI tag
63
68
  # containing the input. Change this from `config/initializers/formtastic.rb`.
64
- @@field_error_proc = proc { |html_tag, instance_tag| html_tag }
65
- mattr_accessor :field_error_proc
69
+ @@formtastic_field_error_proc = proc { |html_tag, instance_tag| html_tag }
70
+ mattr_accessor :formtastic_field_error_proc
66
71
 
67
72
  # Wrapper around Rails' own `form_for` helper to set the `:builder` option to
68
73
  # `Formtastic::FormBuilder` and to set some class names on the `<form>` tag such as
@@ -156,11 +161,13 @@ module Formtastic
156
161
 
157
162
  class_names = options[:html][:class] ? options[:html][:class].split(" ") : []
158
163
  class_names << @@default_form_class
159
- class_names << case record_or_name_or_array
164
+ model_class_name = case record_or_name_or_array
160
165
  when String, Symbol then record_or_name_or_array.to_s # :post => "post"
161
166
  when Array then options[:as] || singularizer.call(record_or_name_or_array.last.class) # [@post, @comment] # => "comment"
162
167
  else options[:as] || singularizer.call(record_or_name_or_array.class) # @post => "post"
163
168
  end
169
+ class_names << @@default_form_model_class_proc.call(model_class_name)
170
+
164
171
  options[:html][:class] = class_names.compact.join(" ")
165
172
 
166
173
  with_custom_field_error_proc do
@@ -186,13 +193,11 @@ module Formtastic
186
193
 
187
194
  def with_custom_field_error_proc(&block)
188
195
  default_field_error_proc = ::ActionView::Base.field_error_proc
189
- ::ActionView::Base.field_error_proc = @@field_error_proc
196
+ ::ActionView::Base.field_error_proc = @@formtastic_field_error_proc
190
197
  yield
191
198
  ensure
192
199
  ::ActionView::Base.field_error_proc = default_field_error_proc
193
200
  end
194
-
195
-
196
201
  end
197
202
  end
198
203
  end
@@ -182,6 +182,10 @@ module Formtastic
182
182
  # <%= f.inputs %>
183
183
  # <% end %>
184
184
  #
185
+ # @example Quick form: Skip one or more fields
186
+ # <%= f.inputs, :except => [:featured, :something_for_admin_only] %>
187
+ # <%= f.inputs, :except => :featured %>
188
+ #
185
189
  # @example Short hand: Render inputs for a named set of attributes and simple associations on the model, with all default arguments and options
186
190
  # <% semantic_form_for @post do |form| %>
187
191
  # <%= f.inputs, :title, :body, :user, :categories %>
@@ -284,6 +288,7 @@ module Formtastic
284
288
  html_options = args.extract_options!
285
289
  html_options[:class] ||= "inputs"
286
290
  html_options[:name] = title
291
+ skipped_args = Array.wrap html_options.delete(:except)
287
292
 
288
293
  out = begin
289
294
  if html_options[:for] # Nested form
@@ -292,7 +297,7 @@ module Formtastic
292
297
  field_set_and_list_wrapping(*(args << html_options), &block)
293
298
  else
294
299
  legend = args.shift if args.first.is_a?(::String)
295
- args = default_columns_for_object if @object && args.empty?
300
+ args = default_columns_for_object - skipped_args if @object && args.empty?
296
301
  contents = fieldset_contents_from_column_list(args)
297
302
  args.unshift(legend) if legend.present?
298
303
  field_set_and_list_wrapping(*((args << html_options) << contents))
@@ -124,7 +124,7 @@ module Formtastic
124
124
  # Avoids an issue where `send_or_call` can be a String and duck can be something simple like
125
125
  # `:first`, which obviously String responds to.
126
126
  def send_or_call_or_object(duck, object)
127
- return object if object.is_a?(String) || object.is_a?(Integer) # TODO what about other classes etc?
127
+ return object if object.is_a?(String) || object.is_a?(Integer) || object.is_a?(Symbol) # TODO what about other classes etc?
128
128
  send_or_call(duck, object)
129
129
  end
130
130
 
@@ -35,7 +35,7 @@ module Formtastic
35
35
  return true unless validator.options.key?(:if) || validator.options.key?(:unless)
36
36
  conditional = validator.options.key?(:if) ? validator.options[:if] : validator.options[:unless]
37
37
 
38
- result = if conditional.respond_to?(:call)
38
+ result = if conditional.respond_to?(:call) && conditional.arity > 0
39
39
  conditional.call(object)
40
40
  elsif conditional.is_a?(::Symbol) && object.respond_to?(conditional)
41
41
  object.send(conditional)
@@ -51,21 +51,11 @@ module Formtastic
51
51
  )
52
52
  end
53
53
 
54
- # TODO: why are we merging `input_html_options` and then making some of the irrelevant ones `nil`?
55
- # Seems like we should be selectively including from input_html_options (a whitelist) instead of
56
- # excluding (blacklist).
57
54
  def label_html_options
58
- prev = super
59
- prev[:class] = prev[:class] - ['label']
60
-
61
- input_html_options.merge(
62
- prev.merge(
63
- :id => nil,
64
- :name => nil,
65
- :tabindex => nil,
66
- :for => input_html_options[:id]
67
- )
68
- )
55
+ {
56
+ :for => input_html_options[:id],
57
+ :class => super[:class] - ['label'] # remove 'label' class
58
+ }
69
59
  end
70
60
 
71
61
  def label_text_with_embedded_checkbox
@@ -46,6 +46,9 @@ module Formtastic
46
46
  # <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1], ["Rails", 2]] %>
47
47
  # <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1, {'data-attr' => 'attr-value'}]] %>
48
48
  # <%= f.input :categories, :as => :check_boxes, :collection => 1..5 %>
49
+ # <%= f.input :categories, :as => :check_boxes, :collection => [:ruby, :rails] %>
50
+ # <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", :ruby], ["Rails", :rails]] %>
51
+ # <%= f.input :categories, :as => :check_boxes, :collection => Set.new([:ruby, :rails]) %>
49
52
  #
50
53
  # @example `:hidden_fields` can be used to skip Rails' rendering of a hidden field before every checkbox
51
54
  # <%= f.input :categories, :as => :check_boxes, :hidden_fields => false %>
@@ -182,7 +185,10 @@ module Formtastic
182
185
 
183
186
  def make_selected_values
184
187
  if object.respond_to?(method)
185
- selected_items = [object.send(method)].compact.flatten
188
+ selected_items = object.send(method)
189
+
190
+ # Construct an array from the return value, regardless of the return type
191
+ selected_items = [*selected_items].compact.flatten
186
192
 
187
193
  [*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
188
194
  else
@@ -83,6 +83,8 @@ module Formtastic
83
83
  # <%= f.input :author, :as => :radio, :collection => [["Justin", "justin"], ["Kate", "kate"]] %>
84
84
  # <%= f.input :author, :as => :radio, :collection => [["Justin", "1"], ["Kate", "3"]] %>
85
85
  # <%= f.input :author, :as => :radio, :collection => [["Justin", 1], ["Kate", 3]] %>
86
+ # <%= f.input :author, :as => :radio, :collection => [["Justin", :justin], ["Kate", :kate]] %>
87
+ # <%= f.input :author, :as => :radio, :collection => [:justin, :kate] %>
86
88
  # <%= f.input :author, :as => :radio, :collection => 1..5 %>
87
89
  #
88
90
  # @example The `:member_label` can be used to call a different method (or a Proc) on each object in the collection for rendering the label text (it'll try the methods like `to_s` in `collection_label_methods` config by default)
@@ -24,9 +24,21 @@ module Formtastic
24
24
  def rails3?
25
25
  ::Rails::VERSION::MAJOR == 3
26
26
  end
27
+
28
+ def rails4?
29
+ ::Rails::VERSION::MAJOR == 4
30
+ end
31
+
32
+ def rails4_0?
33
+ ::Rails::VERSION::MAJOR == 4 && ::Rails::VERSION::MINOR == 0
34
+ end
35
+
36
+ def rails4_1?
37
+ ::Rails::VERSION::MAJOR == 4 && ::Rails::VERSION::MINOR == 1
38
+ end
27
39
 
28
40
  def deprecated_version_of_rails?
29
- const_defined?(:Rails) && ::Rails::VERSION::MAJOR == 3 && ::Rails::VERSION::MINOR < 2
41
+ const_defined?(:Rails) && ::Rails::VERSION::MAJOR == 3 && ::Rails::VERSION::MINOR < 2 && ::Rails::VERSION::PATCH < 13
30
42
  end
31
43
 
32
44
  end