Permalink
Browse files

automatic deduction of errors related to file type fields

  • Loading branch information...
1 parent 3d33932 commit deb9f9b6434c9d5a9bda54dd7e446d730b46f4a5 Aditya Sanghi committed with Oct 28, 2010
Showing with 36 additions and 43 deletions.
  1. +0 −7 README.textile
  2. +18 −7 lib/formtastic.rb
  3. +8 −29 spec/errors_spec.rb
  4. +7 −0 spec/spec_helper.rb
  5. +3 −0 spec/support/custom_macros.rb
View
7 README.textile
@@ -478,13 +478,6 @@ You can show errors on base (by default) and any other attribute just passing it
<% end %>
</pre>
-If you want to include inline errors on fields including the original field (for e.g. Paperclip adds errors on @:document_file_name@@ and @:document_file_size@ and @:document_content_type@ instead of @:document@), provide one or more keys with @:errors_on@ option
-
-<pre>
- <% semantic_form_for @post do |form| %>
- <%= form.input :document, :errors_on => [:document_file_size, :document_file_name] %>
- <% end %>
-</pre>
h2. ValidationReflection plugin
View
25 lib/formtastic.rb
@@ -7,7 +7,7 @@ module Formtastic #:nodoc:
class SemanticFormBuilder < ActionView::Helpers::FormBuilder
class_inheritable_accessor :default_text_field_size, :default_text_area_height, :default_text_area_width, :all_fields_required_by_default, :include_blank_for_select_by_default,
- :required_string, :optional_string, :inline_errors, :label_str_method, :collection_value_methods, :collection_label_methods,
+ :required_string, :optional_string, :inline_errors, :label_str_method, :collection_value_methods, :collection_label_methods, :file_metadata_suffixes,
:inline_order, :custom_inline_order, :file_methods, :priority_countries, :i18n_lookups_by_default, :escape_html_entities_in_hints_and_labels,
:default_commit_button_accesskey, :default_inline_error_class, :default_hint_class, :default_error_list_class, :instance_reader => false
@@ -27,6 +27,7 @@ class SemanticFormBuilder < ActionView::Helpers::FormBuilder
self.inline_order = [ :input, :hints, :errors ]
self.custom_inline_order = {}
self.file_methods = [ :file?, :public_filename, :filename ]
+ self.file_metadata_suffixes = ['content_type', 'file_name', 'file_size']
self.priority_countries = ["Australia", "Canada", "United Kingdom", "United States"]
self.i18n_lookups_by_default = false
self.escape_html_entities_in_hints_and_labels = true
@@ -494,10 +495,13 @@ def semantic_errors(*args)
protected
def error_keys(method, options)
- methods_for_error = [method.to_sym]
- methods_for_error << [options[:errors_on]].flatten.compact.map{|x|x.to_sym}
- methods_for_error << [association_primary_key(method)] if association_macro_for_method(method) == :belongs_to
- methods_for_error.flatten.compact.uniq
+ @methods_for_error ||= {}
+ @methods_for_error[method] ||= begin
+ methods_for_error = [method.to_sym]
+ methods_for_error << self.class.file_metadata_suffixes.map{|suffix| "#{method}_#{suffix}".to_sym} if is_file?(method, options)
+ methods_for_error << [association_primary_key(method)] if association_macro_for_method(method) == :belongs_to
+ methods_for_error.flatten.compact.uniq
+ end
end
def has_errors?(method, options)
@@ -1463,8 +1467,7 @@ def default_input_type(method, options = {}) #:nodoc:
if @object
return :select if self.reflection_for(method)
- file = @object.send(method) if @object.respond_to?(method)
- return :file if file && self.class.file_methods.any? { |m| file.respond_to?(m) }
+ return :file if is_file?(method)
end
return :select if options.key?(:collection)
@@ -1473,6 +1476,14 @@ def default_input_type(method, options = {}) #:nodoc:
end
end
+ def is_file?(method, options = {})
+ @files ||= {}
+ @files[method] ||= (options[:as].present? && options[:as] == :file) || begin
+ file = @object.send(method) if @object && @object.respond_to?(method)
+ file && self.class.file_methods.any?{|m| file.respond_to?(m)}
+ end
+ end
+
# Used by select and radio inputs. The collection can be retrieved by
# three ways:
#
View
37 spec/errors_spec.rb
@@ -129,42 +129,21 @@
end
end
- describe "when error keys are specified as options" do
- it "should show errors on specified key" do
+ describe 'when file type columns have errors' do
+ it "should list errors added on metadata fields" do
@errors.stub!(:[]).with(:document_file_name).and_return(['must be provided'])
- @errors.stub!(:[]).with(:title).and_return([])
- ::Formtastic::SemanticFormBuilder.inline_errors = :sentence
- form = semantic_form_for(@new_post) do |builder|
- builder.input(:title, :errors_on => :document_file_name)
- end
- output_buffer.concat(form) if Formtastic::Util.rails3?
- output_buffer.should have_tag('p.inline-errors', (['must be provided']).to_sentence)
- output_buffer.should have_tag("li[@class='string optional error']")
- end
+ @errors.stub!(:[]).with(:document_file_size).and_return(['must be less than 4mb'])
+ @errors.stub!(:[]).with(:document_content_type).and_return(['must be an image'])
+ @errors.stub!(:[]).with(:document).and_return(nil)
- it "should show errors on original method" do
- @errors.stub!(:[]).with(:document_file_name).and_return(['must be provided'])
- @errors.stub!(:[]).with(:title).and_return(@title_errors)
::Formtastic::SemanticFormBuilder.inline_errors = :sentence
form = semantic_form_for(@new_post) do |builder|
- builder.input(:title, :errors_on => :document_file_name)
+ builder.input(:document)
end
- output_buffer.concat(form) if Formtastic::Util.rails3?
- output_buffer.should have_tag('p.inline-errors', (@title_errors+['must be provided']).to_sentence)
- output_buffer.should have_tag("li[@class='string optional error']")
- end
- it "should show errors all specified keys" do
- @errors.stub!(:[]).with(:document_file_name).and_return(['must be provided'])
- @errors.stub!(:[]).with(:document_content_type).and_return(['must be an image file'])
- @errors.stub!(:[]).with(:title).and_return(@title_errors)
- ::Formtastic::SemanticFormBuilder.inline_errors = :sentence
- form = semantic_form_for(@new_post) do |builder|
- builder.input(:title, :errors_on => [:document_file_name, :document_content_type])
- end
output_buffer.concat(form) if Formtastic::Util.rails3?
- output_buffer.should have_tag('p.inline-errors', (@title_errors+['must be provided', 'must be an image file']).to_sentence)
- output_buffer.should have_tag("li[@class='string optional error']")
+ output_buffer.should have_tag("li[@class='file optional error']")
+ output_buffer.should have_tag('p.inline-errors', (['must be an image','must be provided', 'must be less than 4mb']).to_sentence)
end
end
View
7 spec/spec_helper.rb
@@ -235,6 +235,11 @@ def new_author_path; "/authors/new"; end
::Post.stub!(:persisted?).and_return(nil)
::Post.stub!(:to_ary)
+ @mock_file = mock('file')
+ ::Formtastic::SemanticFormBuilder.file_methods.each do |method|
+ @mock_file.stub!(method).and_return(true)
+ end
+
@new_post.stub!(:title)
@new_post.stub!(:email)
@new_post.stub!(:url)
@@ -256,6 +261,7 @@ def new_author_path; "/authors/new"; end
@new_post.stub!(:country)
@new_post.stub!(:country_subdivision)
@new_post.stub!(:country_code)
+ @new_post.stub!(:document).and_return(@mock_file)
@new_post.stub!(:column_for_attribute).with(:meta_description).and_return(mock('column', :type => :string, :limit => 255))
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 50))
@new_post.stub!(:column_for_attribute).with(:body).and_return(mock('column', :type => :text))
@@ -271,6 +277,7 @@ def new_author_path; "/authors/new"; end
@new_post.stub!(:column_for_attribute).with(:url).and_return(mock('column', :type => :string, :limit => 255))
@new_post.stub!(:column_for_attribute).with(:phone).and_return(mock('column', :type => :string, :limit => 255))
@new_post.stub!(:column_for_attribute).with(:search).and_return(mock('column', :type => :string, :limit => 255))
+ @new_post.stub!(:column_for_attribute).with(:document).and_return(nil)
@new_post.stub!(:author).and_return(@bob)
@new_post.stub!(:author_id).and_return(@bob.id)
View
3 spec/support/custom_macros.rb
@@ -173,6 +173,9 @@ def it_should_apply_error_logic_for_input_type(type)
@title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
@errors = mock('errors')
@errors.stub!(:[]).with(:title).and_return(@title_errors)
+ ::Formtastic::SemanticFormBuilder.file_metadata_suffixes.each do |suffix|
+ @errors.stub!(:[]).with("title_#{suffix}".to_sym).and_return(nil)
+ end
@new_post.stub!(:errors).and_return(@errors)
end

0 comments on commit deb9f9b

Please sign in to comment.