diff options
Diffstat (limited to 'activerecord/lib/active_record/reflection.rb')
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index dede453e38..cf949a893f 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/class/attribute' -require 'active_support/core_ext/object/inclusion' module ActiveRecord # = Active Record Reflection @@ -17,17 +15,36 @@ module ActiveRecord # and creates input fields for all of the attributes depending on their type # and displays the associations to other objects. # - # MacroReflection class has info for the AssociationReflection - # class. + # MacroReflection class has info for AggregateReflection and AssociationReflection + # classes. module ClassMethods def create_reflection(macro, name, scope, options, active_record) - klass = options[:through] ? ThroughReflection : AssociationReflection - reflection = klass.new(macro, name, scope, options, active_record) + case macro + when :has_many, :belongs_to, :has_one, :has_and_belongs_to_many + klass = options[:through] ? ThroughReflection : AssociationReflection + reflection = klass.new(macro, name, scope, options, active_record) + when :composed_of + reflection = AggregateReflection.new(macro, name, scope, options, active_record) + end self.reflections = self.reflections.merge(name => reflection) reflection end + # Returns an array of AggregateReflection objects for all the aggregations in the class. + def reflect_on_all_aggregations + reflections.values.grep(AggregateReflection) + end + + # Returns the AggregateReflection object for the named +aggregation+ (use the symbol). + # + # Account.reflect_on_aggregation(:balance) # => the balance AggregateReflection + # + def reflect_on_aggregation(aggregation) + reflection = reflections[aggregation] + reflection if reflection.is_a?(AggregateReflection) + end + # Returns an array of AssociationReflection objects for all the # associations in the class. If you only want to reflect on a certain # association type, pass in the symbol (<tt>:has_many</tt>, <tt>:has_one</tt>, @@ -59,15 +76,18 @@ module ActiveRecord end end - # Abstract base class for AssociationReflection. Objects of AssociationReflection are returned by the Reflection::ClassMethods. + # Abstract base class for AggregateReflection and AssociationReflection. Objects of + # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. class MacroReflection # Returns the name of the macro. # + # <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>:balance</tt> # <tt>has_many :clients</tt> returns <tt>:clients</tt> attr_reader :name # Returns the macro type. # + # <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>:composed_of</tt> # <tt>has_many :clients</tt> returns <tt>:has_many</tt> attr_reader :macro @@ -75,6 +95,7 @@ module ActiveRecord # Returns the hash of options used for the macro. # + # <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>{ :class_name => "Money" }</tt> # <tt>has_many :clients</tt> returns +{}+ attr_reader :options @@ -94,6 +115,7 @@ module ActiveRecord # Returns the class for the macro. # + # <tt>composed_of :balance, :class_name => 'Money'</tt> returns the Money class # <tt>has_many :clients</tt> returns the Client class def klass @klass ||= class_name.constantize @@ -101,6 +123,7 @@ module ActiveRecord # Returns the class name for the macro. # + # <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>'Money'</tt> # <tt>has_many :clients</tt> returns <tt>'Client'</tt> def class_name @class_name ||= (options[:class_name] || derive_class_name).to_s @@ -122,6 +145,16 @@ module ActiveRecord end end + + # Holds all the meta-data about an aggregation as it was specified in the + # Active Record class. + class AggregateReflection < MacroReflection #:nodoc: + def mapping + mapping = options[:mapping] || [name, name] + mapping.first.is_a?(Array) ? mapping : [mapping] + end + end + # Holds all the meta-data about an association as it was specified in the # Active Record class. class AssociationReflection < MacroReflection #:nodoc: |