Permalink
Browse files

Automatically set maxlength if object is an ActiveModel and the field…

…s method has a maximum length validation
  • Loading branch information...
1 parent 099fb73 commit 98ceff5e9efac372f17bcf3e70181d6641736505 @koppen koppen committed with mjonuschat Aug 27, 2010
Showing with 141 additions and 12 deletions.
  1. +16 −1 lib/formtastic.rb
  2. +113 −7 spec/inputs/string_input_spec.rb
  3. +12 −4 spec/spec_helper.rb
View
@@ -1634,7 +1634,6 @@ def default_string_options(method, type) #:nodoc:
def get_maxlength_for(method)
# TODO: Extract this into a validations_for method in line with reflection_for, and update here and in method_required?
if @object && @object.class.respond_to?(:reflect_on_validations_for)
-
validation = @object.class.reflect_on_validations_for(method).find { |validation|
validation.macro == :validates_length_of &&
validation.name == method
@@ -1644,6 +1643,22 @@ def get_maxlength_for(method)
else
validation_max_limit = nil
end
+ else
+ # ActiveModel?
+ if @object && @object.class.respond_to?(:validators_on)
+ validation = @object.class.validators_on(method).find{ |validator|
+ validator.kind == :length &&
+ (validator.options.present? ? options_require_validation?(validator.options) : true)
+ }
+
+ if validation
+ validation_max_limit = validation.options[:maximum] || (validation.options[:within].present? ? validation.options[:within].max : nil)
+ else
+ validation_max_limit = nil
+ end
+ else
+ validation_max_limit = nil
+ end
end
return validation_max_limit
end
@@ -32,14 +32,15 @@
it_should_apply_custom_for_to_label_when_input_html_id_provided(:string)
it_should_apply_error_logic_for_input_type(:string)
- describe 'and the validation reflection plugin is available' do
- def input_field_for_method_should_have_maxlength(method, maxlength)
- form = semantic_form_for(@new_post) do |builder|
- concat(builder.input(method))
- end
- output_buffer.concat(form) if Formtastic::Util.rails3?
- output_buffer.should have_tag("form li input[@maxlength='#{maxlength}']")
+ def input_field_for_method_should_have_maxlength(method, maxlength)
+ form = semantic_form_for(@new_post) do |builder|
+ concat(builder.input(method))
end
+ output_buffer.concat(form) if Formtastic::Util.rails3?
+ output_buffer.should have_tag("form li input[@maxlength='#{maxlength}']")
+ end
+
+ describe 'and the validation reflection plugin is available' do
describe 'and validates_length_of was called for the method' do
it 'should have a maxlength matching validation range top' do
@@ -65,6 +66,111 @@ def input_field_for_method_should_have_maxlength(method, maxlength)
end
end
end
+
+ describe 'and its a ActiveModel' do
+ let(:default_maxlength) { 50 }
+
+ before do
+ @new_post.stub!(:class).and_return(::PostModel)
+ end
+
+ after do
+ @new_post.stub!(:class).and_return(::Post)
+ end
+
+ describe 'and validates_length_of was called for the method' do
+ it 'should have a maxlength' do
+ @new_post.class.should_receive(:validators_on).with(:title).at_least(2).and_return([
+ active_model_length_validator([:title], {:within => 5..42})
+ ])
+
+ @new_post.class.should_receive(:validators_on).with(:body).at_least(2).and_return([
+ active_model_length_validator([:body], {:if => true, :maximum => 42})
+ ])
+
+ input_field_for_method_should_have_maxlength(:title, 42)
+ input_field_for_method_should_have_maxlength(:body, 42)
+ end
+
+ it 'should have default maxlength if the optional :if condition is not satisifed' do
+ @new_post.class.should_receive(:validators_on).with(:title).at_least(2).and_return([
+ active_model_length_validator([:title], {:maximum => 42, :if => false})
+ ])
+
+ input_field_for_method_should_have_maxlength(:title, default_maxlength)
+ end
+
+ # TODO make a matcher for this?
+ def should_be_required(options)
+ @new_post.class.should_receive(:validators_on).with(:body).and_return([
+ active_model_presence_validator([:body], options[:options])
+ ])
+
+ form = semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:body))
+ end
+
+ output_buffer.concat(form) if Formtastic::Util.rails3?
+
+ if options[:required]
+ output_buffer.should_not have_tag('form li.optional')
+ output_buffer.should have_tag('form li.required')
+ else
+ output_buffer.should have_tag('form li.optional')
+ output_buffer.should_not have_tag('form li.required')
+ end
+ end
+
+ def should_have_maxlength(maxlength, options)
+ @new_post.class.should_receive(:validators_on).with(:title).at_least(2).and_return([
+ active_model_length_validator([:title], options[:options])
+ ])
+
+ form = semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:title))
+ end
+
+ output_buffer.concat(form) if Formtastic::Util.rails3?
+ output_buffer.should have_tag("form li input[@maxlength='#{maxlength}']")
+ end
+
+ it 'should have default_maxlength if the optional :if proc evaluates to false' do
+ should_have_maxlength(default_maxlength, :options => {:maximum => 42, :if => proc { |record| false }})
+ end
+
+ it 'should have maxlength if the optional :if proc evaluates to true' do
+ should_have_maxlength(42, :options => { :maximum => 42, :if => proc { |record| true } })
+ end
+
+ it 'should have default maxlength if the optional :if with a method name evaluates to false' do
+ @new_post.should_receive(:specify_maxlength).and_return(false)
+ should_have_maxlength(default_maxlength, :options => { :maximum => 42, :if => :specify_maxlength })
+ end
+
+ it 'should have maxlength if the optional :if with a method name evaluates to true' do
+ @new_post.should_receive(:specify_maxlength).and_return(true)
+ should_have_maxlength(42, :options => { :maximum => 42, :if => :specify_maxlength })
+ end
+
+ it 'should have default maxlength if the optional :unless proc evaluates to true' do
+ should_have_maxlength(default_maxlength, :options => { :maximum => 42, :unless => proc { |record| true } })
+ end
+
+ it 'should have maxlength if the optional :unless proc evaluates to false' do
+ should_have_maxlength(42, :options => { :maximum => 42, :unless => proc { |record| false } })
+ end
+
+ it 'should have default maxlength if the optional :unless with a method name evaluates to true' do
+ @new_post.should_receive(:specify_maxlength).and_return(true)
+ should_have_maxlength(default_maxlength, :options => { :maximum => 42, :unless => :specify_maxlength })
+ end
+
+ it 'should have maxlength if the optional :unless with a method name evaluates to false' do
+ @new_post.should_receive(:specify_maxlength).and_return(false)
+ should_have_maxlength(42, :options => { :maximum => 42, :unless => :specify_maxlength })
+ end
+ end
+ end
end
describe "when no object is provided" do
View
@@ -53,12 +53,20 @@ def default_input_type(column_type, column_name = :generic_column_name)
return @default_type
end
+ def active_model_validator(kind, attributes, options = {})
+ validator = mock("ActiveModel::Validations::#{kind.to_s.titlecase}Validator", :attributes => attributes, :options => options)
+ validator.stub!(:kind).and_return(kind)
+ validator
+ end
+
def active_model_presence_validator(attributes, options = {})
- presence_validator = mock('ActiveModel::Validations::PresenceValidator', :attributes => attributes, :options => options)
- presence_validator.stub!(:kind).and_return(:presence)
- presence_validator
+ active_model_validator(:presence, attributes, options)
end
-
+
+ def active_model_length_validator(attributes, options = {})
+ active_model_validator(:length, attributes, options)
+ end
+
class ::Post
extend ActiveModel::Naming if defined?(ActiveModel::Naming)
include ActiveModel::Conversion if defined?(ActiveModel::Conversion)

0 comments on commit 98ceff5

Please sign in to comment.