formtastic 3.0.0 → 3.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.travis.yml +1 -0
  2. data/Appraisals +4 -0
  3. data/CHANGELOG +12 -22
  4. data/DEPRECATIONS +47 -0
  5. data/README.textile +9 -4
  6. data/formtastic.gemspec +3 -3
  7. data/gemfiles/rails_4.2.gemfile +7 -0
  8. data/lib/formtastic.rb +13 -7
  9. data/lib/formtastic/action_class_finder.rb +18 -0
  10. data/lib/formtastic/deprecation.rb +42 -0
  11. data/lib/formtastic/form_builder.rb +12 -6
  12. data/lib/formtastic/helpers/action_helper.rb +43 -6
  13. data/lib/formtastic/helpers/form_helper.rb +2 -2
  14. data/lib/formtastic/helpers/input_helper.rb +71 -31
  15. data/lib/formtastic/html_attributes.rb +12 -1
  16. data/lib/formtastic/input_class_finder.rb +18 -0
  17. data/lib/formtastic/inputs.rb +1 -0
  18. data/lib/formtastic/inputs/base.rb +11 -12
  19. data/lib/formtastic/inputs/base/choices.rb +1 -1
  20. data/lib/formtastic/inputs/base/collections.rb +1 -1
  21. data/lib/formtastic/inputs/base/html.rb +3 -3
  22. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  23. data/lib/formtastic/inputs/file_input.rb +2 -2
  24. data/lib/formtastic/namespaced_class_finder.rb +89 -0
  25. data/lib/formtastic/util.rb +1 -1
  26. data/lib/formtastic/version.rb +1 -1
  27. data/lib/generators/templates/formtastic.rb +20 -0
  28. data/spec/action_class_finder_spec.rb +12 -0
  29. data/spec/builder/custom_builder_spec.rb +2 -2
  30. data/spec/builder/semantic_fields_for_spec.rb +4 -4
  31. data/spec/helpers/action_helper_spec.rb +9 -355
  32. data/spec/helpers/form_helper_spec.rb +11 -1
  33. data/spec/helpers/input_helper_spec.rb +1 -916
  34. data/spec/helpers/namespaced_action_helper_spec.rb +43 -0
  35. data/spec/helpers/namespaced_input_helper_spec.rb +36 -0
  36. data/spec/input_class_finder_spec.rb +10 -0
  37. data/spec/inputs/check_boxes_input_spec.rb +2 -2
  38. data/spec/inputs/datalist_input_spec.rb +61 -0
  39. data/spec/inputs/select_input_spec.rb +1 -1
  40. data/spec/localizer_spec.rb +2 -2
  41. data/spec/namespaced_class_finder_spec.rb +79 -0
  42. data/spec/spec_helper.rb +17 -7
  43. data/spec/support/custom_macros.rb +22 -4
  44. data/spec/support/shared_examples.rb +1244 -0
  45. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  46. data/spec/support/test_environment.rb +1 -1
  47. data/spec/util_spec.rb +20 -6
  48. metadata +66 -15
  49. checksums.yaml +0 -15
@@ -11,6 +11,7 @@ gemfile:
11
11
  - gemfiles/rails_4.gemfile
12
12
  - gemfiles/rails_4.0.4.gemfile
13
13
  - gemfiles/rails_4.1.gemfile
14
+ - gemfiles/rails_4.2.gemfile
14
15
  - gemfiles/rails_edge.gemfile
15
16
  env:
16
17
  - DEFER_GC=false RAILS_EDGE=true
data/Appraisals CHANGED
@@ -15,6 +15,10 @@ appraise 'rails-4.1' do
15
15
  gem 'rails', '~>4.1.0'
16
16
  end
17
17
 
18
+ appraise 'rails-4.2' do
19
+ gem 'rails', '~>4.2.0.beta4'
20
+ end
21
+
18
22
  if ENV["RAILS_EDGE"] == "true"
19
23
  appraise 'rails-edge' do
20
24
  gem 'rails', :git => 'git://github.com/rails/rails.git'
data/CHANGELOG CHANGED
@@ -1,27 +1,17 @@
1
- 3.0.0
1
+ 3.1.0.rc1 (unreleased)
2
2
 
3
- * No changes since 3.0.0.rc2
3
+ * Deprecated support for Rails version < 4.1.0
4
+ * Fixed synchronization issues with custom_namespace configuration
5
+ * Fixed bug where boolean (checkbox) inputs were not being correctly checked (also in 2.3.1)
6
+ * Fixed (silenced) Rails 5 deprecation on column_for_attribute that we're handling fine
7
+ * Added new DatalistInput (:as => :datalist) for HTML5 datalists
8
+ * Added configurable namespaces for custom inputs
9
+ * Various performance and documentation improvements
4
10
 
5
- 3.0.0.rc2
11
+ ---
6
12
 
7
- * Fixed bug where boolean (checkbox) inputs were not being correctly checked
13
+ See 3.0-stable branch for 3.0.x changes
14
+ https://github.com/justinfrench/formtastic/blob/3.0-stable/CHANGELOG
8
15
 
9
-
10
- 3.0.0.rc
11
-
12
- * Removed support for Ruby version < 1.9.3
13
- * Removed support for Rails version < 3.2.13
14
- * Removed deprecated option :input_html => { :value => '...'} (#1025)
15
- * Removed deprecated option :hint_class (#1025)
16
- * Removed deprecated option :error_class (#1025)
17
- * Removed deprecated option :group_by (#1025)
18
- * Removed deprecated option :group_label (#1025)
19
- * Removed deprecated option :find_options (#1025)
20
- * Deprecated support for Rails < 4.0.4
21
- * Changed i18n lookups to use the `:as` option from the form builder (#1033)
22
- * Improved documentation for country_select gem compatibility & support (#1061)
23
- * Improved documentation for browser support of datetime and datetime-local (#1029)
24
- * Added support for ColorInput (:as => :color) in Rails 4 (#1039)
25
-
26
- See 2.3-stable branch for earlier releases
16
+ See 2.3-stable branch for 2.3.x and earlier releases
27
17
  https://github.com/justinfrench/formtastic/blob/2.3-stable/CHANGELOG
@@ -0,0 +1,47 @@
1
+ This document is for tracking deprecations and removals of
2
+ Formtastic features and compatibilities.
3
+
4
+ v4.0 (planned)
5
+
6
+ * Remove support for Rails < 4.1
7
+ * Remove support for country_select 1.x syntax (they want to remove it in 3.0)
8
+
9
+ v3.1 (master)
10
+
11
+ * Deprecate support for Rails < 4.1
12
+
13
+ v3.0
14
+
15
+ * Remove support for Ruby version < 1.9.3
16
+ * Remove support for Rails version < 3.2.13
17
+ * Remove deprecated option :value (#1025)
18
+ * Remove deprecated option :hint_class (#1025)
19
+ * Remove deprecated option :error_class (#1025)
20
+ * Remove deprecated option :group_by (#1025)
21
+ * Remove deprecated option :group_label (#1025)
22
+ * Remove deprecated option :find_options (#1025)
23
+ * Deprecate support for Rails < 4.0.4
24
+
25
+ v2.3
26
+
27
+ * Remove deprecated date, time and datetime inputs
28
+ * Deprecate :error_class option
29
+ * Deprecate support for Rails < 3.2.13
30
+
31
+ v2.2
32
+
33
+ * Remove deprecated buttons DSL, ButtonHelper and commit_button helper
34
+ * Deprecate :value option
35
+ * Deprecate :hint_class option
36
+ * Deprecate :error_class option
37
+ * Deprecate :group_by and :group_label options
38
+ * Deprecate :find_options option
39
+
40
+ v2.1
41
+
42
+ * Remove the previously deprecated :label_method, :value_method & :group_label_method options
43
+ * Remove the previously deprecated :as => :numeric
44
+ * Remove the previously deprecated inline_errors_for and related methods
45
+ * Remove the previously deprecated SemanticFormHelper and SemanticFormBuilder
46
+ * Deprecate the Buttons DSL (f.buttons, f.commit_button) in favor of the new Actions DSL — see above
47
+
@@ -20,9 +20,10 @@ h2. Documentation & Support
20
20
 
21
21
  h2. Compatibility
22
22
 
23
- * Formtastic 3 (master on Github) will require Rails 3.2.13 minimum
24
- * Formtastic 2.3 is Rails 3 and Rails 4 compatible (Rails < 3.2.13 is deprecated)
25
- * Formtastic 2.1 & 2.2 is Rails 3 and Rails 4 compatible
23
+ * Formtastic 3.1 (master branch) will require Rails 4.1 minimum
24
+ * Formtastic 3.0 requires Rails 3.2.13 minimum
25
+ * Formtastic 2.3 deprecated Rails < 3.2.13
26
+ * Formtastic 2.1, 2.2 & 2.3 are Rails 3.x–4.1.x compatible
26
27
  * 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!
27
28
 
28
29
 
@@ -93,7 +94,7 @@ h2. Installation
93
94
  Simply add Formtastic to your Gemfile and bundle it up:
94
95
 
95
96
  <pre>
96
- gem 'formtastic'
97
+ gem 'formtastic', '~> 3.0'
97
98
  </pre>
98
99
 
99
100
  Run the installation generator:
@@ -315,6 +316,7 @@ Many inputs provide a collection of options to choose from (like @:select@, @:ra
315
316
  f.input :author, :as => :radio, :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"]
316
317
  f.input :admin, :as => :radio, :collection => ["Yes!", "No"]
317
318
  f.input :book_id, :as => :select, :collection => Hash[Book.all.map{|b| [b.name,b.id]}]
319
+ f.input :fav_book,:as => :datalist , :collection => Book.pluck(:name)
318
320
  </pre>
319
321
 
320
322
 
@@ -342,6 +344,7 @@ The Formtastic input types:
342
344
  * @:search@ - a text field (just like string). Default for columns with name matching @"search"@. New in HTML5. Works on Safari.
343
345
  * @:hidden@ - a hidden field. Creates a hidden field (added for compatibility).
344
346
  * @:range@ - a slider field.
347
+ * @:datalist@ - a text field with a accompanying "datalist tag":https://developer.mozilla.org/en/docs/Web/HTML/Element/datalist which provides options for autocompletion
345
348
 
346
349
  The comments in the code are pretty good for each of these (what it does, what the output is, what the options are, etc.) so go check it out.
347
350
 
@@ -516,6 +519,8 @@ For more flexible forms; Formtastic finds translations using a bottom-up approac
516
519
 
517
520
  Values for @labels@/@hints@/@actions@ are can take values: @String@ (explicit value), @Symbol@ (i18n-lookup-key relative to the current "type", e.g. actions:), @true@ (force I18n lookup), @false@ (force no I18n lookup). Titles (legends) can only take: @String@ and @Symbol@ - true/false have no meaning.
518
521
 
522
+ *7. Basic Translations*
523
+ If you want some basic translations, take a look on the "formtastic_i18n gem":https://github.com/timoschilling/formtastic_i18n.
519
524
 
520
525
  h2. Semantic errors
521
526
 
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
27
27
 
28
28
  s.add_dependency(%q<actionpack>, [">= 3.2.13"])
29
29
 
30
- s.add_development_dependency(%q<nokogiri>, ["< 1.6.0"]) # 1.6 requires Ruby 1.9.2, drop in v3.0
30
+ s.add_development_dependency(%q<nokogiri>)
31
31
  s.add_development_dependency(%q<rspec-rails>, ["~> 2.14"])
32
32
  s.add_development_dependency(%q<rspec_tag_matchers>, ["~> 1.0"])
33
33
  s.add_development_dependency(%q<hpricot>, ["~> 0.8.3"])
@@ -35,8 +35,8 @@ Gem::Specification.new do |s|
35
35
  s.add_development_dependency(%q<yard>, ["~> 0.6"])
36
36
  s.add_development_dependency(%q<colored>, ["~> 1.2"])
37
37
  s.add_development_dependency(%q<tzinfo>)
38
- s.add_development_dependency(%q<ammeter>, ["0.2.5"])
38
+ s.add_development_dependency(%q<ammeter>, ["1.1.1"])
39
39
  s.add_development_dependency(%q<appraisal>, ["~> 1.0"])
40
- s.add_development_dependency(%q<rake>, ["<= 10.1.1"]) # Anything higher requires Ruby 1.9, drop in v3.0
40
+ s.add_development_dependency(%q<rake>)
41
41
  s.add_development_dependency(%q<activemodel>, [">= 3.2.13"])
42
42
  end
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~>4.2.0.beta4"
6
+
7
+ gemspec :path => "../"
@@ -13,25 +13,31 @@ module Formtastic
13
13
  autoload :LocalizedString
14
14
  autoload :Localizer
15
15
  autoload :Util
16
-
16
+ autoload :NamespacedClassFinder
17
+ autoload :InputClassFinder
18
+ autoload :ActionClassFinder
19
+ autoload :Deprecation
20
+
21
+ # @private
22
+ mattr_accessor :deprecation
23
+ self.deprecation = Formtastic::Deprecation.new('4.0', 'Formtastic')
24
+
17
25
  if defined?(::Rails) && Util.deprecated_version_of_rails?
18
- ::ActiveSupport::Deprecation.warn(
19
- "Support for Rails < 4.0.4 will be dropped from Formtastic 4.0",
20
- caller)
26
+ deprecation.warn("Support for Rails < 4.0.4 will be dropped ")
21
27
  end
22
28
 
23
29
  # @private
24
30
  class UnknownInputError < NameError
25
31
  end
26
-
32
+
27
33
  # @private
28
34
  class UnknownActionError < NameError
29
35
  end
30
-
36
+
31
37
  # @private
32
38
  class PolymorphicInputWithoutCollectionError < ArgumentError
33
39
  end
34
-
40
+
35
41
  # @private
36
42
  class UnsupportedMethodForAction < ArgumentError
37
43
  end
@@ -0,0 +1,18 @@
1
+ module Formtastic
2
+
3
+ # Uses the +NamespacedClassFinder+ to look up action class names.
4
+ #
5
+ # See +Formtastic::Helpers::ActionHelper#namespaced_action_class+ for details.
6
+ #
7
+ class ActionClassFinder < NamespacedClassFinder
8
+ def initialize(builder)
9
+ super builder.action_namespaces
10
+ end
11
+
12
+ private
13
+
14
+ def class_name(as)
15
+ "#{super}Action"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ require 'active_support/deprecation'
2
+
3
+ # TODO: remove this branch and file when support for rails 3.2 is dropped
4
+
5
+ module Formtastic
6
+ if ActiveSupport::Deprecation.respond_to?(:new)
7
+ Deprecation = ActiveSupport::Deprecation
8
+ else
9
+ require 'forwardable'
10
+
11
+ class Deprecation
12
+ mattr_accessor :deprecation
13
+ self.deprecation = ActiveSupport::Deprecation.dup
14
+
15
+ extend Forwardable
16
+ methods = deprecation.methods - deprecation.class.methods
17
+ def_delegators :deprecation, *methods
18
+
19
+ def initialize(version, _library)
20
+ deprecation.silenced = false
21
+ deprecation.deprecation_horizon = version
22
+ end
23
+
24
+ def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
25
+ caller_backtrace ||= caller(2)
26
+
27
+ deprecated_method_warning(deprecated_method_name, message).tap do |msg|
28
+ warn(msg, caller_backtrace)
29
+ end
30
+ end
31
+
32
+ def deprecated_method_warning(method_name, message = nil)
33
+ warning = "#{method_name} is deprecated and will be removed from Formtastic #{deprecation_horizon}"
34
+ case message
35
+ when Symbol then "#{warning} (use #{message} instead)"
36
+ when String then "#{warning} (#{message})"
37
+ else warning
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -31,6 +31,12 @@ module Formtastic
31
31
  configure :default_hint_class, 'inline-hints'
32
32
  configure :use_required_attribute, false
33
33
  configure :perform_browser_validations, false
34
+ configure :input_namespaces, [::Object, ::Formtastic::Inputs]
35
+ # TODO: enable this as default in 4.0 and remove it from configuration generator template
36
+ configure :input_class_finder #, Formtastic::InputClassFinder
37
+ configure :action_namespaces, [::Object, ::Formtastic::Actions]
38
+ # TODO: enable this as default in 4.0 and remove it from configuration generator template
39
+ configure :action_class_finder#, Formtastic::ActionClassFinder
34
40
 
35
41
  attr_reader :template
36
42
 
@@ -43,8 +49,8 @@ module Formtastic
43
49
  include Formtastic::Helpers::ActionHelper
44
50
  include Formtastic::Helpers::ActionsHelper
45
51
  include Formtastic::Helpers::ErrorsHelper
46
-
47
- # This is a wrapper around Rails' `ActionView::Helpers::FormBuilder#fields_for`, originally
52
+
53
+ # This is a wrapper around Rails' `ActionView::Helpers::FormBuilder#fields_for`, originally
48
54
  # provided to ensure that the `:builder` from `semantic_form_for` was passed down into
49
55
  # the nested `fields_for`. Rails 3 no longer requires us to do this, so this method is
50
56
  # provided purely for backwards compatibility and DSL consistency.
@@ -76,11 +82,11 @@ module Formtastic
76
82
  # Add a :parent_builder to the args so that nested translations can be possible in Rails 3
77
83
  options = args.extract_options!
78
84
  options[:parent_builder] ||= self
79
-
85
+
80
86
  # Wrap the Rails helper
81
87
  fields_for(record_or_name_or_array, *(args << options), &block)
82
88
  end
83
-
89
+
84
90
  def initialize(object_name, object, template, options, block=nil)
85
91
  # rails 3 supported passing in the block parameter to FormBuilder
86
92
  # rails 4.0 deprecated the block parameter and does nothing with it
@@ -90,12 +96,12 @@ module Formtastic
90
96
  else # Must be rails4_1 or greater
91
97
  super object_name, object, template, options
92
98
  end
93
-
99
+
94
100
  if respond_to?('multipart=') && options.is_a?(Hash) && options[:html]
95
101
  self.multipart = options[:html][:multipart]
96
102
  end
97
103
  end
98
-
104
+
99
105
  end
100
106
 
101
107
  end
@@ -2,7 +2,9 @@
2
2
  module Formtastic
3
3
  module Helpers
4
4
  module ActionHelper
5
-
5
+ ACTION_CLASS_DEPRECATION = 'configure Formtastic::FormBuilder.action_class_finder instead'.freeze
6
+ private_constant(:ACTION_CLASS_DEPRECATION)
7
+
6
8
  # Renders an action for the form (such as a subit/reset button, or a cancel link).
7
9
  #
8
10
  # Each action is wrapped in an `<li class="action">` tag with other classes added based on the
@@ -23,9 +25,9 @@ module Formtastic
23
25
  # reset: "Reset form"
24
26
  # submit: "Submit"
25
27
  #
26
- # For forms with an object present, the `update` key will be used if calling `persisted?` on
27
- # the object returns true (saving changes to a record), otherwise the `create` ey will be
28
- # used. The `submit` key is used as a fallback when there is no object or we cannot determine
28
+ # For forms with an object present, the `update` key will be used if calling `persisted?` on
29
+ # the object returns true (saving changes to a record), otherwise the `create` key will be
30
+ # used. The `submit` key is used as a fallback when there is no object or we cannot determine
29
31
  # if `create` or `update` is appropriate.
30
32
  #
31
33
  # @example Basic usage
@@ -90,12 +92,35 @@ module Formtastic
90
92
  def default_action_type(method, options = {}) #:nodoc:
91
93
  case method
92
94
  when :submit then :input
93
- when :reset then :input
95
+ when :reset then :input
94
96
  when :cancel then :link
97
+ else method
95
98
  end
96
99
  end
97
100
 
101
+ # Takes the `:as` option and attempts to return the corresponding action
102
+ # class. In the case of `:as => :awesome` it will first attempt to find a
103
+ # top level `AwesomeAction` class (to allow the application to subclass
104
+ # and modify to suit), falling back to `Formtastic::Actions::AwesomeAction`.
105
+ #
106
+ # Custom action namespaces to look into can be configured via the
107
+ # .action_namespaces +FormBuilder+ configuration setting.
108
+ # See +Formtastic::Helpers::InputHelper#namespaced_input_class+ for details.
109
+ #
110
+ def namespaced_action_class(as)
111
+ @action_class_finder ||= action_class_finder.new(self)
112
+ @action_class_finder.find(as)
113
+ rescue Formtastic::ActionClassFinder::NotFoundError => e
114
+ raise Formtastic::UnknownActionError, "Unable to find action #{e.message}"
115
+ end
116
+
117
+ # @api private
118
+ # @deprecated Use {#namespaced_action_class} instead.
98
119
  def action_class(as)
120
+ return namespaced_action_class(as) if action_class_finder
121
+
122
+ action_class_deprecation_warning(__method__)
123
+
99
124
  @input_classes_cache ||= {}
100
125
  @input_classes_cache[as] ||= begin
101
126
  begin
@@ -105,21 +130,33 @@ module Formtastic
105
130
  standard_action_class_name(as).constantize
106
131
  end
107
132
  rescue NameError
108
- raise Formtastic::UnknownActionError
133
+ raise Formtastic::UnknownActionError, "Unable to find action #{as}"
109
134
  end
110
135
  end
111
136
  end
112
137
 
138
+ # @api private
139
+ # @deprecated Use {Formtastic::ActionClassFinder#class_name} instead.
113
140
  # :as => :button # => ButtonAction
114
141
  def custom_action_class_name(as)
142
+ action_class_deprecation_warning(__method__)
115
143
  "#{as.to_s.camelize}Action"
116
144
  end
117
145
 
146
+ # @api private
147
+ # @deprecated Use {Formtastic::ActionClassFinder#class_name} instead.
118
148
  # :as => :button # => Formtastic::Actions::ButtonAction
119
149
  def standard_action_class_name(as)
150
+ action_class_deprecation_warning(__method__)
120
151
  "Formtastic::Actions::#{as.to_s.camelize}Action"
121
152
  end
122
153
 
154
+ private
155
+
156
+ def action_class_deprecation_warning(method)
157
+ @action_class_deprecation_warned ||=
158
+ Formtastic.deprecation.deprecation_warning(method, ACTION_CLASS_DEPRECATION, caller(2))
159
+ end
123
160
  end
124
161
  end
125
162
  end
@@ -155,7 +155,7 @@ module Formtastic
155
155
  options[:builder] ||= @@builder
156
156
  options[:html] ||= {}
157
157
  options[:html][:novalidate] = !@@builder.perform_browser_validations unless options[:html].key?(:novalidate)
158
- @@builder.custom_namespace = options.delete(:namespace).to_s
158
+ options[:custom_namespace] = options.delete(:namespace)
159
159
 
160
160
  singularizer = defined?(ActiveModel::Naming.singular) ? ActiveModel::Naming.method(:singular) : ActionController::RecordIdentifier.method(:singular_class_name)
161
161
 
@@ -182,7 +182,7 @@ module Formtastic
182
182
  def semantic_fields_for(record_name, record_object = nil, options = {}, &block)
183
183
  options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
184
184
  options[:builder] ||= @@builder
185
- @@builder.custom_namespace = options.delete(:namespace).to_s # TODO needed?
185
+ options[:custom_namespace] = options.delete(:namespace)
186
186
 
187
187
  with_custom_field_error_proc do
188
188
  self.fields_for(record_name, record_object, options, &block)