aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorEloy Duran <eloy.de.enige@gmail.com>2010-01-03 21:45:08 +0100
committerEloy Duran <eloy.de.enige@gmail.com>2010-01-07 13:19:48 +0100
commitb6264c43f414f323656ed135d46213466cbe00fb (patch)
tree9bc78cfd200f5b977e77178ac0c37b8660922a93 /activerecord/lib/active_record
parentfc6aae34597bbecaf441571b20ab861b021ea8a5 (diff)
downloadrails-b6264c43f414f323656ed135d46213466cbe00fb.tar.gz
rails-b6264c43f414f323656ed135d46213466cbe00fb.tar.bz2
rails-b6264c43f414f323656ed135d46213466cbe00fb.zip
Moved the validation logic to the association reflection and refactored autosave_association.rb a bit.
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/autosave_association.rb39
-rw-r--r--activerecord/lib/active_record/reflection.rb13
2 files changed, 29 insertions, 23 deletions
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index b3e28b9373..f01d0903cd 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -158,46 +158,39 @@ module ActiveRecord
#
# For performance reasons, we don't check whether to validate at runtime,
# but instead only define the method and callback when needed. However,
- # this can change, for instance, when using nested attributes. Since we
- # don't want the callbacks to get defined multiple times, there are
- # guards that check if the save or validation methods have already been
- # defined before actually defining them.
+ # this can change, for instance, when using nested attributes, which is
+ # called _after_ the association has been defined. Since we don't want
+ # the callbacks to get defined multiple times, there are guards that
+ # check if the save or validation methods have already been defined
+ # before actually defining them.
def add_autosave_association_callbacks(reflection)
save_method = :"autosave_associated_records_for_#{reflection.name}"
validation_method = :"validate_associated_records_for_#{reflection.name}"
- force_validation = (reflection.options[:validate] == true || reflection.options[:autosave] == true)
+ collection = reflection.collection_association?
- if reflection.collection_association?
- unless method_defined?(save_method)
+ unless method_defined?(save_method)
+ if collection
before_save :before_save_collection_association
define_method(save_method) { save_collection_association(reflection) }
# Doesn't use after_save as that would save associations added in after_create/after_update twice
after_create save_method
after_update save_method
- end
-
- if !method_defined?(validation_method) &&
- (force_validation || (reflection.macro == :has_many && reflection.options[:validate] != false))
- define_method(validation_method) { validate_collection_association(reflection) }
- validate validation_method
- end
- else
- unless method_defined?(save_method)
- case reflection.macro
- when :has_one
+ else
+ if reflection.macro == :has_one
define_method(save_method) { save_has_one_association(reflection) }
after_save save_method
- when :belongs_to
+ else
define_method(save_method) { save_belongs_to_association(reflection) }
before_save save_method
end
end
+ end
- if !method_defined?(validation_method) && force_validation
- define_method(validation_method) { validate_single_association(reflection) }
- validate validation_method
- end
+ if reflection.validate? && !method_defined?(validation_method)
+ method = (collection ? :validate_collection_association : :validate_single_association)
+ define_method(validation_method) { send(method, reflection) }
+ validate validation_method
end
end
end
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 96aac96cda..d6fad5cf29 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -262,6 +262,19 @@ module ActiveRecord
@collection_association
end
+ # Returns whether or not the association should be validated as part of
+ # the parent's validation.
+ #
+ # Unless you explicitely disable validation with
+ # <tt>:validate => false</tt>, it will take place when:
+ #
+ # * you explicitely enable validation; <tt>:validate => true</tt>
+ # * you use autosave; <tt>:autosave => true</tt>
+ # * the association is a +has_many+ association
+ def validate?
+ !options[:validate].nil? ? options[:validate] : (options[:autosave] == true || macro == :has_many)
+ end
+
private
def derive_class_name
class_name = name.to_s.camelize