formtastic 2.2.1 → 2.3.0.rc

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 +17 -13
  2. data/Appraisals +6 -3
  3. data/CHANGELOG +4 -0
  4. data/Gemfile +1 -1
  5. data/README.textile +14 -23
  6. data/Rakefile +0 -17
  7. data/app/assets/stylesheets/formtastic.css +2 -1
  8. data/formtastic.gemspec +4 -3
  9. data/gemfiles/{rails-3.0.gemfile → rails_3.0.gemfile} +1 -1
  10. data/gemfiles/{rails-3.1.gemfile → rails_3.1.gemfile} +1 -1
  11. data/gemfiles/{rails-3.2.gemfile → rails_3.2.gemfile} +1 -1
  12. data/gemfiles/rails_4.gemfile +7 -0
  13. data/gemfiles/rails_edge.gemfile +7 -0
  14. data/lib/formtastic/form_builder.rb +7 -0
  15. data/lib/formtastic/helpers/fieldset_wrapper.rb +1 -1
  16. data/lib/formtastic/helpers/form_helper.rb +8 -10
  17. data/lib/formtastic/helpers/input_helper.rb +1 -0
  18. data/lib/formtastic/inputs/base.rb +0 -1
  19. data/lib/formtastic/inputs/base/collections.rb +15 -4
  20. data/lib/formtastic/inputs/base/labelling.rb +4 -7
  21. data/lib/formtastic/inputs/base/numeric.rb +1 -1
  22. data/lib/formtastic/inputs/base/options.rb +1 -1
  23. data/lib/formtastic/inputs/base/timeish.rb +12 -4
  24. data/lib/formtastic/inputs/boolean_input.rb +6 -6
  25. data/lib/formtastic/inputs/check_boxes_input.rb +7 -2
  26. data/lib/formtastic/inputs/datetime_picker_input.rb +3 -3
  27. data/lib/formtastic/inputs/select_input.rb +4 -2
  28. data/lib/formtastic/util.rb +4 -0
  29. data/lib/formtastic/version.rb +1 -1
  30. data/lib/generators/templates/formtastic.rb +3 -3
  31. data/sample/basic_inputs.html +1 -1
  32. data/spec/builder/semantic_fields_for_spec.rb +0 -1
  33. data/spec/helpers/action_helper_spec.rb +1 -1
  34. data/spec/helpers/form_helper_spec.rb +30 -0
  35. data/spec/helpers/input_helper_spec.rb +1 -1
  36. data/spec/helpers/inputs_helper_spec.rb +13 -15
  37. data/spec/inputs/boolean_input_spec.rb +7 -0
  38. data/spec/inputs/check_boxes_input_spec.rb +31 -1
  39. data/spec/inputs/date_select_input_spec.rb +8 -0
  40. data/spec/inputs/datetime_picker_input_spec.rb +14 -14
  41. data/spec/inputs/datetime_select_input_spec.rb +8 -0
  42. data/spec/inputs/label_spec.rb +11 -0
  43. data/spec/inputs/select_input_spec.rb +21 -4
  44. data/spec/inputs/time_select_input_spec.rb +9 -1
  45. data/spec/spec_helper.rb +74 -13
  46. data/spec/support/custom_macros.rb +3 -2
  47. data/spec/support/test_environment.rb +2 -0
  48. metadata +116 -40
  49. data/gemfiles/rails-4.gemfile +0 -8
  50. data/lib/tasks/verify_rcov.rb +0 -44
@@ -1,26 +1,30 @@
1
- before_install: gem update --system
1
+ before_install:
2
+ - gem update --system
3
+ - gem update bundler
2
4
  rvm:
3
5
  - 1.8.7
4
6
  - ree
5
7
  - 1.9.2
6
8
  - 1.9.3
7
9
  gemfile:
8
- - gemfiles/rails-3.0.gemfile
9
- - gemfiles/rails-3.1.gemfile
10
- - gemfiles/rails-3.2.gemfile
11
- - gemfiles/rails-4.gemfile
10
+ - gemfiles/rails_3.0.gemfile
11
+ - gemfiles/rails_3.1.gemfile
12
+ - gemfiles/rails_3.2.gemfile
12
13
  env:
13
14
  - DEFER_GC=false RAILS_EDGE=true
14
15
  script: "rake spec"
15
16
  matrix:
16
- exclude:
17
- - rvm: 1.8.7
18
- gemfile: gemfiles/rails-4.gemfile
17
+ include:
18
+ - rvm: 1.9.3
19
+ gemfile: gemfiles/rails_4.gemfile
19
20
  env: DEFER_GC=false RAILS_EDGE=true
20
- - rvm: ree
21
- gemfile: gemfiles/rails-4.gemfile
21
+ - rvm: 2.0.0
22
+ gemfile: gemfiles/rails_4.gemfile
22
23
  env: DEFER_GC=false RAILS_EDGE=true
23
- - rvm: 1.9.2
24
- gemfile: gemfiles/rails-4.gemfile
24
+ allow_failures:
25
+ - rvm: 1.9.3
26
+ gemfile: gemfiles/rails_edge.gemfile
27
+ env: DEFER_GC=false RAILS_EDGE=true
28
+ - rvm: 2.0.0
29
+ gemfile: gemfiles/rails_edge.gemfile
25
30
  env: DEFER_GC=false RAILS_EDGE=true
26
-
data/Appraisals CHANGED
@@ -10,9 +10,12 @@ appraise 'rails-3.2' do
10
10
  gem 'rails', '~> 3.2.0'
11
11
  end
12
12
 
13
+ appraise 'rails-4' do
14
+ gem 'rails', '~> 4.0.0'
15
+ end
16
+
13
17
  if ENV["RAILS_EDGE"] == "true"
14
- appraise 'rails-4' do
18
+ appraise 'rails-edge' do
15
19
  gem 'rails', :git => 'git://github.com/rails/rails.git'
16
- gem 'active_record_deprecated_finders', :git=>'https://github.com/rails/active_record_deprecated_finders.git'
17
20
  end
18
- end
21
+ end
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ HEAD
2
+
3
+ * Allow to use a custom ActionView::Base.field_error_proc
4
+
1
5
  2.2.1
2
6
 
3
7
  * Rails 4 compatibilty updates
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
@@ -5,6 +5,15 @@ Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far e
5
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>
6
6
 
7
7
 
8
+ h2. Documentation & Support
9
+
10
+ * "Documentation is available on rdoc.info":http://rdoc.info/projects/justinfrench/formtastic
11
+ * "We track issues & bugs on GitHub":http://github.com/justinfrench/formtastic/issues
12
+ * "We have a wiki on GitHub":http://github.com/justinfrench/formtastic/wiki
13
+ * "StackOverflow can help":http://stackoverflow.com/questions/tagged/formtastic
14
+ * "Follow @formtastic on Twitter for news & updates":http://twitter.com/formtastic
15
+
16
+
8
17
  h2. Compatibility
9
18
 
10
19
  * Formtastic 2.1.x is Rails 3.x compatible
@@ -75,11 +84,6 @@ h2. Opinions
75
84
  * Make the common things we do easy, yet ensure uncommon things are still possible.
76
85
 
77
86
 
78
- h2. Documentation
79
-
80
- RDoc documentation _should_ be automatically generated after each commit and made available on the "rdoc.info website":http://rdoc.info/projects/justinfrench/formtastic.
81
-
82
-
83
87
  h2. Installation
84
88
 
85
89
  Simply add Formtastic to your Gemfile and bundle it up:
@@ -250,12 +254,7 @@ Alternatively, the current index can be accessed via the `inputs` block's argume
250
254
  <pre>
251
255
  <%= semantic_form_for @post do |f| %>
252
256
  <%= f.inputs :for => :categories do |category, i| %>
253
- <% if i <= 2 %>
254
- <%= f.inputs :name => "Category ##{i}" %>
255
- <% else %>
256
- <%= f.inputs :name => "Category ##{i} (optional)" %>
257
- <% end %>
258
- <% end %>
257
+ ...
259
258
  <%= f.actions %>
260
259
  <% end %>
261
260
  </pre>
@@ -531,7 +530,7 @@ Values for @labels@/@hints@/@actions@ are can take values: @String@ (explicit va
531
530
 
532
531
  h2. Semantic errors
533
532
 
534
- You can show errors on base (by default) and any other attribute just passing it name to semantic_errors method:
533
+ You can show errors on base (by default) and any other attribute just by passing its name to the semantic_errors method:
535
534
 
536
535
  <pre>
537
536
  <%= semantic_form_for @post do |f| %>
@@ -608,28 +607,20 @@ Formtastic::FormBuilder.escape_html_entities_in_hints_and_labels = false
608
607
 
609
608
  h2. Dependencies
610
609
 
611
- There are none, but...
610
+ There are none other than Rails itself, but...
612
611
 
613
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).
614
- * "rspec":http://github.com/dchelimsky/rspec/, "rspec_hpricot_matchers":http://rubyforge.org/projects/rspec-hpricot/ and "rcov":http://github.com/relevance/rcov gems (plus any of their own dependencies) are required for the test suite.
613
+ * There are a bunch of development dependencies
615
614
 
616
615
 
617
616
  h2. How to contribute
618
617
 
619
618
  * Fork the project on Github
620
619
  * Create a topic branch for your changes
620
+ * Ensure that you provide test coverage for your changes
621
621
  * Ensure that all tests pass (`bundle exec rake`)
622
- * Ensure that the changes in your branch are as atomic as possible
623
622
  * Create a pull request on Github
624
623
 
625
- For significant changes, you may wish to discuss your idea on the Formtastic Google group before coding to ensure that your change is likely to be accepted. Formtastic relies heavily on i18n, so if you're unsure of the impact this has on your changes, please discuss them with the group.
626
-
627
-
628
- h2. Google Group, Twitter, etc
629
-
630
- Please join the "Formtastic Google Group":http://groups.google.com.au/group/formtastic, especially if you'd like to talk about a new feature, or report a bug.
631
-
632
- You can also follow "@justinfrench":http://twitter.com/formtastic or "@formtastic":http://twitter.com/formtastic on Twitter for announcements, tutorials and links.
633
624
 
634
625
  h2. Project Info
635
626
 
data/Rakefile CHANGED
@@ -3,7 +3,6 @@ require 'bundler/setup'
3
3
  require 'appraisal'
4
4
  require 'rdoc/task'
5
5
  require 'rspec/core/rake_task'
6
- require 'tasks/verify_rcov'
7
6
 
8
7
  Bundler::GemHelper.install_tasks
9
8
 
@@ -38,19 +37,3 @@ desc 'Test the formtastic plugin with specdoc formatting and colors'
38
37
  RSpec::Core::RakeTask.new('specdoc') do |t|
39
38
  t.pattern = FileList['spec/**/*_spec.rb']
40
39
  end
41
-
42
- desc 'Run all examples with RCov'
43
- RSpec::Core::RakeTask.new('rcov') do |t|
44
- t.pattern = FileList['spec/**/*_spec.rb']
45
- t.rcov = true
46
- t.rcov_opts = %w(--exclude gems/*,spec/*,.bundle/*, --aggregate coverage.data)
47
- end
48
-
49
- RCov::VerifyTask.new(:verify_coverage) do |t|
50
- t.require_exact_threshold = false
51
- t.threshold = (RUBY_VERSION == "1.8.7" ? 95 : 0)
52
- end
53
-
54
- desc "Run all examples and verify coverage"
55
- task :spec_and_verify_coverage => [:rcov, :verify_coverage] do
56
- end
@@ -194,7 +194,8 @@ This stylesheet forms part of the Formtastic Rails Plugin
194
194
  width:72%;
195
195
  }
196
196
 
197
- .formtastic .stringish input[size] {
197
+ .formtastic .stringish input[size],
198
+ .formtastic .stringish input[max] {
198
199
  width:auto;
199
200
  max-width:72%;
200
201
  }
@@ -25,15 +25,16 @@ Gem::Specification.new do |s|
25
25
 
26
26
  s.add_dependency(%q<actionpack>, [">= 3.0"])
27
27
 
28
- s.add_development_dependency(%q<rspec-rails>, ["~> 2.8.0"])
28
+ 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"])
29
30
  s.add_development_dependency(%q<rspec_tag_matchers>, [">= 1.0.0"])
30
31
  s.add_development_dependency(%q<hpricot>, ["~> 0.8.3"])
31
32
  s.add_development_dependency(%q<BlueCloth>) # for YARD
32
33
  s.add_development_dependency(%q<yard>, ["~> 0.6"])
33
- s.add_development_dependency(%q<rcov>, ["~> 0.9.9"])
34
34
  s.add_development_dependency(%q<colored>)
35
35
  s.add_development_dependency(%q<tzinfo>)
36
- s.add_development_dependency(%q<ammeter>, ["~> 0.2.5"])
36
+ s.add_development_dependency(%q<ammeter>, ["0.2.5"])
37
37
  s.add_development_dependency(%q<appraisal>)
38
38
  s.add_development_dependency(%q<rake>)
39
+ s.add_development_dependency(%q<activemodel>)
39
40
  end
@@ -1,6 +1,6 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source :rubygems
3
+ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.0.0"
6
6
 
@@ -1,6 +1,6 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source :rubygems
3
+ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.1.0"
6
6
 
@@ -1,6 +1,6 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source :rubygems
3
+ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.2.0"
6
6
 
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.0.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", :git=>"git://github.com/rails/rails.git"
6
+
7
+ gemspec :path=>"../"
@@ -81,6 +81,13 @@ module Formtastic
81
81
  fields_for(record_or_name_or_array, *(args << options), &block)
82
82
  end
83
83
 
84
+ def initialize(object_name, object, template, options, block=nil)
85
+ super
86
+ if respond_to?('multipart=') && options.is_a?(Hash) && options[:html]
87
+ self.multipart = options[:html][:multipart]
88
+ end
89
+ end
90
+
84
91
  end
85
92
 
86
93
  end
@@ -72,7 +72,7 @@ module Formtastic
72
72
  return duck + 1 if duck.is_a?(Fixnum)
73
73
 
74
74
  # First try to extract key from duck Hash, then try child
75
- i = (duck[key] || duck[child]).to_i + 1
75
+ (duck[key] || duck[child]).to_i + 1
76
76
  end
77
77
 
78
78
  end
@@ -58,6 +58,12 @@ module Formtastic
58
58
  @@default_form_class = 'formtastic'
59
59
  mattr_accessor :default_form_class
60
60
 
61
+ # Allows to set a custom field_error_proc wrapper. By default this wrapper
62
+ # is disabled since `formtastic` already adds an error class to the LI tag
63
+ # 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
66
+
61
67
  # Wrapper around Rails' own `form_for` helper to set the `:builder` option to
62
68
  # `Formtastic::FormBuilder` and to set some class names on the `<form>` tag such as
63
69
  # `formtastic` and the downcased and underscored model name (eg `post`).
@@ -155,7 +161,7 @@ module Formtastic
155
161
  when Array then options[:as] || singularizer.call(record_or_name_or_array.last.class) # [@post, @comment] # => "comment"
156
162
  else options[:as] || singularizer.call(record_or_name_or_array.class) # @post => "post"
157
163
  end
158
- options[:html][:class] = class_names.join(" ")
164
+ options[:html][:class] = class_names.compact.join(" ")
159
165
 
160
166
  with_custom_field_error_proc do
161
167
  self.form_for(record_or_name_or_array, *(args << options), &proc)
@@ -178,17 +184,9 @@ module Formtastic
178
184
 
179
185
  protected
180
186
 
181
- # Override the default ActiveRecordHelper behaviour of wrapping the input.
182
- # This gets taken care of semantically by adding an error class to the LI tag
183
- # containing the input.
184
- # @private
185
- FIELD_ERROR_PROC = proc do |html_tag, instance_tag|
186
- html_tag
187
- end
188
-
189
187
  def with_custom_field_error_proc(&block)
190
188
  default_field_error_proc = ::ActionView::Base.field_error_proc
191
- ::ActionView::Base.field_error_proc = FIELD_ERROR_PROC
189
+ ::ActionView::Base.field_error_proc = @@field_error_proc
192
190
  yield
193
191
  ensure
194
192
  ::ActionView::Base.field_error_proc = default_field_error_proc
@@ -232,6 +232,7 @@ module Formtastic
232
232
  # @todo Many many more examples. Some of the detail probably needs to be pushed out to the relevant methods too.
233
233
  # @todo More i18n examples.
234
234
  def input(method, options = {})
235
+ method = method.to_sym if method.is_a?(String)
235
236
  options = options.dup # Allow options to be shared without being tainted by Formtastic
236
237
  options[:as] ||= default_input_type(method, options)
237
238
 
@@ -65,7 +65,6 @@ module Formtastic
65
65
  include Html
66
66
  include Options
67
67
  include Database
68
- include Database
69
68
  include Errors
70
69
  include Hints
71
70
  include Naming
@@ -85,10 +85,21 @@ module Formtastic
85
85
 
86
86
  scope_conditions = conditions_from_reflection.empty? ? nil : {:conditions => conditions_from_reflection}
87
87
  if conditions_from_options.any?
88
- reflection.klass.scoped(scope_conditions).where(conditions_from_options)
88
+ if Util.rails3?
89
+ reflection.klass.scoped(scope_conditions).where(conditions_from_options)
90
+ else
91
+ reflection.klass.where(scope_conditions[:conditions]).where(conditions_from_options)
92
+ end
89
93
  else
90
- find_options_from_options.merge!(:include => group_by) if self.respond_to?(:group_by) && group_by
91
- reflection.klass.scoped(scope_conditions).where(find_options_from_options)
94
+
95
+ if Util.rails3?
96
+ find_options_from_options.merge!(:include => group_by) if self.respond_to?(:group_by) && group_by
97
+ reflection.klass.scoped(scope_conditions).where(find_options_from_options)
98
+ else
99
+ coll = reflection.klass.where(scope_conditions)
100
+ coll = coll.includes(group_by) if self.respond_to?(:group_by) && group_by
101
+ coll.where(find_options_from_options)
102
+ end
92
103
  end
93
104
  end
94
105
  end
@@ -113,7 +124,7 @@ module Formtastic
113
124
  # Avoids an issue where `send_or_call` can be a String and duck can be something simple like
114
125
  # `:first`, which obviously String responds to.
115
126
  def send_or_call_or_object(duck, object)
116
- return object if object.is_a?(String) # TODO what about other classes etc?
127
+ return object if object.is_a?(String) || object.is_a?(Integer) # TODO what about other classes etc?
117
128
  send_or_call(duck, object)
118
129
  end
119
130
 
@@ -10,13 +10,10 @@ module Formtastic
10
10
  end
11
11
 
12
12
  def label_html_options
13
- # opts = options_for_label(options) # TODO
14
- opts = {}
15
- opts[:for] ||= input_html_options[:id]
16
- opts[:class] = [opts[:class]]
17
- opts[:class] << 'label'
18
-
19
- opts
13
+ {
14
+ :for => input_html_options[:id],
15
+ :class => ['label'],
16
+ }
20
17
  end
21
18
 
22
19
  def label_text
@@ -5,7 +5,7 @@ module Formtastic
5
5
  def input_html_options
6
6
  defaults = super
7
7
 
8
- # override rails default size - not valid on numeric inputs
8
+ # override rails default size - does not apply to numeric inputs
9
9
  #@todo document/spec
10
10
  defaults[:size] = nil
11
11
 
@@ -8,7 +8,7 @@ module Formtastic
8
8
  end
9
9
 
10
10
  def formtastic_options
11
- [:priority_countries, :priority_zones, :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, :value_as_class, :find_options, :class]
12
12
  end
13
13
 
14
14
  end
@@ -65,6 +65,9 @@ module Formtastic
65
65
  # @example Change the labels for each fragment
66
66
  # <%= f.input :publish_at, :as => :date_select, :labels => { :year => "Y", :month => "M", :day => "D" } %>
67
67
  #
68
+ # @example Suppress the labels for all fragments
69
+ # <%= f.input :publish_at, :as => :date_select, :labels => false %>
70
+ #
68
71
  # @example Skip a fragment (defaults to 1, skips all following fragments)
69
72
  # <%= f.input :publish_at, :as => :datetime_select, :discard_minute => true %>
70
73
  # <%= f.input :publish_at, :as => :datetime_select, :discard_hour => true %>
@@ -130,8 +133,10 @@ module Formtastic
130
133
  end
131
134
 
132
135
  def fragment_label(fragment)
133
- labels_from_options = options[:labels] || {}
134
- if labels_from_options.key?(fragment)
136
+ labels_from_options = options.key?(:labels) ? options[:labels] : {}
137
+ if !labels_from_options
138
+ ''
139
+ elsif labels_from_options.key?(fragment)
135
140
  labels_from_options[fragment]
136
141
  else
137
142
  ::I18n.t(fragment.to_s, :default => fragment.to_s.humanize, :scope => [:datetime, :prompts])
@@ -183,8 +188,11 @@ module Formtastic
183
188
 
184
189
  def i18n_date_fragments
185
190
  order = ::I18n.t(:order, :scope => [:date])
186
- order = nil unless order.is_a?(Array)
187
- order
191
+ if order.is_a?(Array)
192
+ order.map &:to_sym
193
+ else
194
+ nil
195
+ end
188
196
  end
189
197
 
190
198
  def fragments_wrapping(&block)