Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #610 from julian7/validates_presence

AR validations should be checked better for figuring out required fields
  • Loading branch information...
commit 88fb05f15043021a8d2c88d0911aeb175f8f802d 2 parents daac316 + bbc4052
@justinfrench authored
View
14 lib/formtastic/inputs/base/validations.rb
@@ -121,8 +121,18 @@ def required?
return false if not_required_through_negated_validation?
if validations?
validations.select { |validator|
- [:presence, :inclusion, :length].include?(validator.kind) &&
- validator.options[:allow_blank] != true
+ case validator.kind
+ when :presence
+ true
+ when :inclusion
+ validator.options[:allow_blank] != true
+ when :length
+ validator.options[:allow_blank] != true &&
+ validator.options[:minimum].to_i > 0 ||
+ validator.options[:within].try(:first).to_i > 0
+ else
+ false
+ end
}.any?
else
return responds_to_global_required? && !!builder.all_fields_required_by_default
View
92 spec/helpers/input_helper_spec.rb
@@ -138,43 +138,43 @@
end
it 'should be not be required if the optional :if condition is not satisifed' do
- should_be_required(:required => false, :options => { :if => false })
+ presence_should_be_required(:required => false, :tag => :body, :options => { :if => false })
end
it 'should not be required if the optional :if proc evaluates to false' do
- should_be_required(:required => false, :options => { :if => proc { |record| false } })
+ presence_should_be_required(:required => false, :tag => :body, :options => { :if => proc { |record| false } })
end
it 'should be required if the optional :if proc evaluates to true' do
- should_be_required(:required => true, :options => { :if => proc { |record| true } })
+ presence_should_be_required(:required => true, :tag => :body, :options => { :if => proc { |record| true } })
end
it 'should not be required if the optional :unless proc evaluates to true' do
- should_be_required(:required => false, :options => { :unless => proc { |record| true } })
+ presence_should_be_required(:required => false, :tag => :body, :options => { :unless => proc { |record| true } })
end
it 'should be required if the optional :unless proc evaluates to false' do
- should_be_required(:required => true, :options => { :unless => proc { |record| false } })
+ presence_should_be_required(:required => true, :tag => :body, :options => { :unless => proc { |record| false } })
end
it 'should be required if the optional :if with a method string evaluates to true' do
@new_post.should_receive(:required_condition).and_return(true)
- should_be_required(:required => true, :options => { :if => :required_condition })
+ presence_should_be_required(:required => true, :tag => :body, :options => { :if => :required_condition })
end
it 'should be required if the optional :if with a method string evaluates to false' do
@new_post.should_receive(:required_condition).and_return(false)
- should_be_required(:required => false, :options => { :if => :required_condition })
+ presence_should_be_required(:required => false, :tag => :body, :options => { :if => :required_condition })
end
- it 'should not be required if the optional :unless with a method string evaluates to false' do
+ it 'should be required if the optional :unless with a method string evaluates to false' do
@new_post.should_receive(:required_condition).and_return(false)
- should_be_required(:required => true, :options => { :unless => :required_condition })
+ presence_should_be_required(:required => true, :tag => :body, :options => { :unless => :required_condition })
end
- it 'should be required if the optional :unless with a method string evaluates to true' do
+ it 'should not be required if the optional :unless with a method string evaluates to true' do
@new_post.should_receive(:required_condition).and_return(true)
- should_be_required(:required => false, :options => { :unless => :required_condition })
+ presence_should_be_required(:required => false, :tag => :body, :options => { :unless => :required_condition })
end
end
@@ -183,35 +183,59 @@
@new_post.class.should_receive(:validators_on).with(:published).any_number_of_times.and_return([
active_model_inclusion_validator([:published], {:in => [false, true]})
])
-
- concat(semantic_form_for(@new_post) do |builder|
- concat(builder.input(:published))
- end)
- output_buffer.should have_tag('form li.required')
- output_buffer.should_not have_tag('form li.optional')
+ should_be_required(:tag => :published, :required => true)
end
it 'should not be required if allow_blank is true' do
@new_post.class.should_receive(:validators_on).with(:published).any_number_of_times.and_return([
active_model_inclusion_validator([:published], {:in => [false, true], :allow_blank => true})
])
-
- concat(semantic_form_for(@new_post) do |builder|
- concat(builder.input(:published))
- end)
- output_buffer.should_not have_tag('form li.required')
- output_buffer.should have_tag('form li.optional')
+ should_be_required(:tag => :published, :required => false)
end
end
-
+
+ describe 'and validates_length_of was called for the method' do
+ it 'should be required if minimum is set' do
+ length_should_be_required(:tag => :title, :required => true, :options => {:minimum => 1})
+ end
+
+ it 'should be required if :within is set' do
+ length_should_be_required(:tag => :title, :required => true, :options => {:within => 1..5})
+ end
+
+ it 'should not be required if :within allows zero length' do
+ length_should_be_required(:tag => :title, :required => false, :options => {:within => 0..5})
+ end
+
+ it 'should not be required if only :minimum is zero' do
+ length_should_be_required(:tag => :title, :required => false, :options => {:minimum => 0})
+ end
+
+ it 'should not be required if only :minimum is not set' do
+ length_should_be_required(:tag => :title, :required => false, :options => {:maximum => 5})
+ end
+
+ it 'should not be required if allow_blank is true' do
+ length_should_be_required(:tag => :published, :required => false, :options => {:allow_blank => true})
+ end
+ end
+
+ def add_presence_validator(options)
+ @new_post.class.stub!(:validators_on).with(options[:tag]).and_return([
+ active_model_presence_validator([options[:tag]], options[:options])
+ ])
+ end
+
+ def add_length_validator(options)
+ @new_post.class.should_receive(:validators_on).with(options[:tag]).any_number_of_times {[
+ active_model_length_validator([options[:tag]], options[:options])
+ ]}
+ end
+
# TODO make a matcher for this?
def should_be_required(options)
- @new_post.class.stub!(:validators_on).with(:body).and_return([
- active_model_presence_validator([:body], options[:options])
- ])
-
concat(semantic_form_for(@new_post) do |builder|
- concat(builder.input(:body))
+ concat(builder.input(options[:tag]))
end)
if options[:required]
@@ -222,6 +246,16 @@ def should_be_required(options)
output_buffer.should_not have_tag('form li.required')
end
end
+
+ def presence_should_be_required(options)
+ add_presence_validator(options)
+ should_be_required(options)
+ end
+
+ def length_should_be_required(options)
+ add_length_validator(options)
+ should_be_required(options)
+ end
# TODO JF reversed this during refactor, need to make sure
describe 'and there are no requirement validations on the method' do
Please sign in to comment.
Something went wrong with that request. Please try again.