Lookup errors in associations.

This commit is contained in:
Carlos Antonio da Silva 2009-12-11 01:18:56 -02:00
parent 94cb1efe00
commit 461f309bc7
6 changed files with 32 additions and 15 deletions

View File

@ -9,7 +9,7 @@ module SimpleForm
# of prepending the content available in the method content.
class Base
delegate :template, :object, :object_name, :attribute, :column,
:input_type, :options, :to => :@builder
:reflection, :input_type, :options, :to => :@builder
def self.basename
@basename ||= name.split("::").last.underscore.to_sym

View File

@ -9,11 +9,19 @@ module SimpleForm
end
def errors
@errors ||= object.errors[attribute]
@errors ||= (errors_on_attribute + errors_on_association).compact
end
def errors_on_attribute
Array(object.errors[attribute])
end
def errors_on_association
reflection ? Array(object.errors[reflection.name]) : []
end
def content
component_tag Array(errors).to_sentence
component_tag errors.to_sentence
end
end
end

View File

@ -1,14 +1,15 @@
module SimpleForm
class FormBuilder < ActionView::Helpers::FormBuilder
attr_reader :template, :object_name, :object, :attribute, :column, :input_type, :options
attr_reader :template, :object_name, :object, :attribute, :column,
:reflection, :input_type, :options
TERMINATOR = lambda { "" }
# Basic input helper, combines all components in the stack to generate input
# html based on options the user define and some guesses through
# Basic input helper, combines all components in the stack to generate
# input html based on options the user define and some guesses through
# database column information. By default a call to input will generate
# label + input + hint (when defined) + errors (when exists), and all can be
# configured inside a wrapper html.
# label + input + hint (when defined) + errors (when exists), and all can
# be configured inside a wrapper html.
#
# == Examples:
#
@ -98,18 +99,18 @@ module SimpleForm
def association(attribute, options={})
raise ArgumentError, "Association cannot be used in forms not associated with an object" unless @object
association = find_association(attribute)
raise "Association not found #{attribute.inspect}" unless association
@reflection = find_association_reflection(attribute)
raise "Association not found #{attribute.inspect}" unless @reflection
attribute = association.options[:foreign_key] || :"#{association.name}_id"
attribute = @reflection.options[:foreign_key] || :"#{@reflection.name}_id"
options[:collection] ||= begin
find_options = { :conditions => options.delete(:conditions),
:order => options.delete(:order) }
association.klass.all(find_options)
@reflection.klass.all(find_options)
end
input(attribute, options)
returning(input(attribute, options)) { @reflection = nil }
end
# Creates a button:
@ -248,7 +249,7 @@ module SimpleForm
end
# Find association related to attribute
def find_association(attribute)
def find_association_reflection(attribute)
@object.class.reflect_on_association(attribute) if @object.class.respond_to?(:reflect_on_association)
end

View File

@ -5,6 +5,7 @@ class ErrorTest < ActionView::TestCase
def with_error_for(object, attribute, type, options={}, &block)
simple_form_for object do |f|
f.attribute = attribute
f.reflection = Association.new(Company, :company, {}) if options.delete(:setup_association)
f.input_type = type
f.options = options
@ -46,4 +47,9 @@ class ErrorTest < ActionView::TestCase
with_error_for @user, :name, :string, :error_html => { :id => 'error', :class => 'yay' }
assert_select 'span#error.error.yay'
end
test 'error should find errors on attribute and association' do
with_error_for @user, :company_id, :select, :setup_association => true
assert_select 'span.error', 'must be valid and company must be present'
end
end

View File

@ -64,6 +64,8 @@ class User < OpenStruct
:name => "can't be blank",
:description => "must be longer than 15 characters",
:age => ["is not a number", "must be greater than 18"],
:company => "company must be present",
:company_id => "must be valid"
}
end
end

View File

@ -16,7 +16,7 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
I18n.default_locale = :en
class SimpleForm::FormBuilder
attr_accessor :attribute, :column, :input_type, :options
attr_accessor :attribute, :column, :reflection, :input_type, :options
end
class ActionView::TestCase