diff options
Diffstat (limited to 'activerecord/lib/active_record/reflection.rb')
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 99 |
1 files changed, 43 insertions, 56 deletions
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index bcba85d7a4..98f0418d3f 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/class/attribute' -require 'active_support/core_ext/module/deprecation' require 'active_support/core_ext/object/inclusion' module ActiveRecord @@ -81,12 +80,6 @@ module ActiveRecord # Abstract base class for AggregateReflection and AssociationReflection. Objects of # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. class MacroReflection - attr_reader :active_record - - def initialize(macro, name, options, active_record) - @macro, @name, @options, @active_record = macro, name, options, active_record - end - # Returns the name of the macro. # # <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>:balance</tt> @@ -105,6 +98,19 @@ module ActiveRecord # <tt>has_many :clients</tt> returns +{}+ attr_reader :options + attr_reader :active_record + + attr_reader :plural_name # :nodoc: + + def initialize(macro, name, options, active_record) + @macro = macro + @name = name + @options = options + @active_record = active_record + @plural_name = active_record.pluralize_table_names ? + name.to_s.pluralize : name.to_s + end + # Returns the class for the macro. # # <tt>composed_of :balance, :class_name => 'Money'</tt> returns the Money class @@ -124,7 +130,11 @@ module ActiveRecord # Returns +true+ if +self+ and +other_aggregation+ have the same +name+ attribute, +active_record+ attribute, # and +other_aggregation+ has an options hash assigned to it. def ==(other_aggregation) - other_aggregation.kind_of?(self.class) && name == other_aggregation.name && other_aggregation.options && active_record == other_aggregation.active_record + super || + other_aggregation.kind_of?(self.class) && + name == other_aggregation.name && + other_aggregation.options && + active_record == other_aggregation.active_record end def sanitized_conditions #:nodoc: @@ -169,25 +179,8 @@ module ActiveRecord # Returns a new, unsaved instance of the associated class. +options+ will # be passed to the class's constructor. - def build_association(*options) - klass.new(*options) - end - - # Creates a new instance of the associated class, and immediately saves it - # with ActiveRecord::Base#save. +options+ will be passed to the class's - # creation method. Returns the newly created object. - def create_association(*options) - klass.create(*options) - end - - # Creates a new instance of the associated class, and immediately saves it - # with ActiveRecord::Base#save!. +options+ will be passed to the class's - # creation method. If the created record doesn't pass validations, then an - # exception will be raised. - # - # Returns the newly created object. - def create_association!(*options) - klass.create!(*options) + def build_association(*options, &block) + klass.new(*options, &block) end def table_name @@ -202,17 +195,12 @@ module ActiveRecord @foreign_key ||= options[:foreign_key] || derive_foreign_key end - def primary_key_name - foreign_key - end - deprecate :primary_key_name => :foreign_key - def foreign_type @foreign_type ||= options[:foreign_type] || "#{name}_type" end def type - @type ||= "#{options[:as]}_type" + @type ||= options[:as] && "#{options[:as]}_type" end def primary_key_column @@ -223,22 +211,20 @@ module ActiveRecord @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key end - def association_primary_key - @association_primary_key ||= - options[:primary_key] || - !options[:polymorphic] && klass.primary_key || - 'id' + # klass option is necessary to support loading polymorphic associations + def association_primary_key(klass = nil) + options[:primary_key] || primary_key(klass || self.klass) end def active_record_primary_key - @active_record_primary_key ||= options[:primary_key] || active_record.primary_key + @active_record_primary_key ||= options[:primary_key] || primary_key(active_record) end def counter_cache_column if options[:counter_cache] == true "#{active_record.name.demodulize.underscore.pluralize}_count" elsif options[:counter_cache] - options[:counter_cache] + options[:counter_cache].to_s end end @@ -280,9 +266,7 @@ module ActiveRecord # in the #chain. The inside arrays are simply conditions (and each condition may itself be # a hash, array, arel predicate, etc...) def conditions - conditions = [options[:conditions]].compact - conditions << { type => active_record.base_class.name } if options[:as] - [conditions] + [[options[:conditions]].compact] end alias :source_macro :macro @@ -373,14 +357,19 @@ module ActiveRecord active_record.name.foreign_key end end + + def primary_key(klass) + klass.primary_key || raise(UnknownPrimaryKey.new(klass)) + end end # Holds all the meta-data about a :through association as it was specified # in the Active Record class. class ThroughReflection < AssociationReflection #:nodoc: - delegate :foreign_key, :foreign_type, :association_foreign_key, :active_record_primary_key, :to => :source_reflection + delegate :foreign_key, :foreign_type, :association_foreign_key, + :active_record_primary_key, :type, :to => :source_reflection - # Gets the source of the through reflection. It checks both a singularized + # Gets the source of the through reflection. It checks both a singularized # and pluralized form for <tt>:belongs_to</tt> or <tt>:has_many</tt>. # # class Post < ActiveRecord::Base @@ -444,7 +433,7 @@ module ActiveRecord # of relevant reflections, plus any :source_type or polymorphic :as constraints. def conditions @conditions ||= begin - conditions = source_reflection.conditions + conditions = source_reflection.conditions.map { |c| c.dup } # Add to it the conditions from this reflection if necessary. conditions.first << options[:conditions] if options[:conditions] @@ -476,17 +465,15 @@ module ActiveRecord # We want to use the klass from this reflection, rather than just delegate straight to # the source_reflection, because the source_reflection may be polymorphic. We still # need to respect the source_reflection's :primary_key option, though. - def association_primary_key - @association_primary_key ||= begin - # Get the "actual" source reflection if the immediate source reflection has a - # source reflection itself - source_reflection = self.source_reflection - while source_reflection.source_reflection - source_reflection = source_reflection.source_reflection - end - - source_reflection.options[:primary_key] || klass.primary_key + def association_primary_key(klass = nil) + # Get the "actual" source reflection if the immediate source reflection has a + # source reflection itself + source_reflection = self.source_reflection + while source_reflection.source_reflection + source_reflection = source_reflection.source_reflection end + + source_reflection.options[:primary_key] || primary_key(klass || self.klass) end # Gets an array of possible <tt>:through</tt> source reflection names: |