diff options
author | Jon Leighton <j@jonathanleighton.com> | 2011-02-20 20:42:35 +0000 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2011-02-21 10:16:14 -0800 |
commit | 32eef69dc1abbf9b67de780a882754e1717c2a3b (patch) | |
tree | ec88ff3d6a212e900ff63dbcf49172d501782ea8 /activerecord | |
parent | 73ff0076b37316af685bc411bd11a7908d7794f6 (diff) | |
download | rails-32eef69dc1abbf9b67de780a882754e1717c2a3b.tar.gz rails-32eef69dc1abbf9b67de780a882754e1717c2a3b.tar.bz2 rails-32eef69dc1abbf9b67de780a882754e1717c2a3b.zip |
Delegate Association#options to the reflection, and replace 'reflection.options' with 'options'. Also add through_options and source_options methods for through associations.
Diffstat (limited to 'activerecord')
8 files changed, 57 insertions, 47 deletions
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index fa1200a949..df18afe57a 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -99,12 +99,12 @@ module ActiveRecord def association_scope scope = target_klass.unscoped scope = scope.create_with(creation_attributes) - scope = scope.apply_finder_options(reflection.options.slice(:readonly, :include)) - scope = scope.where(interpolate(reflection.options[:conditions])) + scope = scope.apply_finder_options(options.slice(:readonly, :include)) + scope = scope.where(interpolate(options[:conditions])) if select = select_value scope = scope.select(select) end - scope = scope.extending(*Array.wrap(reflection.options[:extend])) + scope = scope.extending(*Array.wrap(options[:extend])) scope.where(construct_owner_conditions) end @@ -175,7 +175,7 @@ module ActiveRecord end def select_value - reflection.options[:select] + options[:select] end # Implemented by (some) subclasses @@ -191,8 +191,8 @@ module ActiveRecord else attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key] - if reflection.options[:as] - attributes["#{reflection.options[:as]}_type"] = owner.class.base_class.name + if options[:as] + attributes["#{options[:as]}_type"] = owner.class.base_class.name end end attributes diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index c1471c72df..0baaa3a83b 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -56,7 +56,7 @@ module ActiveRecord end def target_id - if reflection.options[:primary_key] + if options[:primary_key] owner.send(reflection.name).try(:id) else owner[reflection.foreign_key] diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 04bea92586..ba98542b67 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -47,7 +47,7 @@ module ActiveRecord end def find(*args) - if reflection.options[:finder_sql] + if options[:finder_sql] find_by_scan(*args) else scoped.find(*args) @@ -145,26 +145,26 @@ module ActiveRecord # Count all records using SQL. If the +:counter_sql+ or +:finder_sql+ option is set for the # association, it will be used for the query. Otherwise, construct options and pass them with # scope to the target class's +count+. - def count(column_name = nil, options = {}) - column_name, options = nil, column_name if column_name.is_a?(Hash) + def count(column_name = nil, count_options = {}) + column_name, count_options = nil, column_name if column_name.is_a?(Hash) - if reflection.options[:counter_sql] || reflection.options[:finder_sql] - unless options.blank? + if options[:counter_sql] || options[:finder_sql] + unless count_options.blank? raise ArgumentError, "If finder_sql/counter_sql is used then options cannot be passed" end reflection.klass.count_by_sql(custom_counter_sql) else - if reflection.options[:uniq] + if options[:uniq] # This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL. column_name ||= reflection.klass.primary_key - options.merge!(:distinct => true) + count_options.merge!(:distinct => true) end - value = scoped.count(column_name, options) + value = scoped.count(column_name, count_options) - limit = reflection.options[:limit] - offset = reflection.options[:offset] + limit = options[:limit] + offset = options[:offset] if limit || offset [ [value - offset.to_i, 0].max, limit.to_i ].min @@ -182,7 +182,7 @@ module ActiveRecord # are actually removed from the database, that depends precisely on # +delete_records+. They are in any case removed from the collection. def delete(*records) - delete_or_destroy(records, reflection.options[:dependent]) + delete_or_destroy(records, options[:dependent]) end # Destroy +records+ and remove them from this association calling @@ -206,11 +206,11 @@ module ActiveRecord # This method is abstract in the sense that it relies on # +count_records+, which is a method descendants have to provide. def size - if owner.new_record? || (loaded? && !reflection.options[:uniq]) + if owner.new_record? || (loaded? && !options[:uniq]) target.size - elsif !loaded? && reflection.options[:group] + elsif !loaded? && options[:group] load_target.size - elsif !loaded? && !reflection.options[:uniq] && target.is_a?(Array) + elsif !loaded? && !options[:uniq] && target.is_a?(Array) unsaved_records = target.select { |r| r.new_record? } unsaved_records.size + count_records else @@ -280,7 +280,7 @@ module ActiveRecord if record.new_record? include_in_memory?(record) else - load_target if reflection.options[:finder_sql] + load_target if options[:finder_sql] loaded? ? target.include?(record) : scoped.exists?(record) end else @@ -319,7 +319,7 @@ module ActiveRecord callback(:before_add, record) yield(record) if block_given? - if reflection.options[:uniq] && index = @target.index(record) + if options[:uniq] && index = @target.index(record) @target[index] = record else @target << record @@ -339,31 +339,31 @@ module ActiveRecord end def uniq_select_value - reflection.options[:uniq] && "DISTINCT #{reflection.quoted_table_name}.*" + options[:uniq] && "DISTINCT #{reflection.quoted_table_name}.*" end def custom_counter_sql - if reflection.options[:counter_sql] - interpolate(reflection.options[:counter_sql]) + if options[:counter_sql] + interpolate(options[:counter_sql]) else # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */ - interpolate(reflection.options[:finder_sql]).sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" } + interpolate(options[:finder_sql]).sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" } end end def custom_finder_sql - interpolate(reflection.options[:finder_sql]) + interpolate(options[:finder_sql]) end def find_target records = - if reflection.options[:finder_sql] + if options[:finder_sql] reflection.klass.find_by_sql(custom_finder_sql) else find(:all) end - records = reflection.options[:uniq] ? uniq(records) : records + records = options[:uniq] ? uniq(records) : records records.each { |record| set_inverse_instance(record) } records end @@ -467,7 +467,7 @@ module ActiveRecord else !(loaded? || owner.new_record? || - reflection.options[:finder_sql] || + options[:finder_sql] || target.any? { |record| record.new_record? || record.changed? } || args.first.kind_of?(Integer)) end diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index b36c814a67..028630977d 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -12,8 +12,8 @@ module ActiveRecord def insert_record(record, validate = true) return if record.new_record? && !record.save(:validate => validate) - if reflection.options[:insert_sql] - owner.connection.insert(interpolate(reflection.options[:insert_sql], record)) + if options[:insert_sql] + owner.connection.insert(interpolate(options[:insert_sql], record)) else stmt = join_table.compile_insert( join_table[reflection.foreign_key] => owner.id, @@ -37,7 +37,7 @@ module ActiveRecord end def delete_records(records, method) - if sql = reflection.options[:delete_sql] + if sql = options[:delete_sql] records.each { |record| owner.connection.delete(interpolate(sql, record)) } else relation = join_table diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index e22498a0a5..5ae81649c5 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -29,7 +29,7 @@ module ActiveRecord def count_records count = if has_cached_counter? owner.send(:read_attribute, cached_counter_attribute_name) - elsif reflection.options[:counter_sql] || reflection.options[:finder_sql] + elsif options[:counter_sql] || options[:finder_sql] reflection.klass.count_by_sql(custom_counter_sql) else scoped.count @@ -40,7 +40,7 @@ module ActiveRecord # documented side-effect of the method that may avoid an extra SELECT. @target ||= [] and loaded! if count == 0 - [reflection.options[:limit], count].compact.min + [options[:limit], count].compact.min end def has_cached_counter?(reflection = reflection) diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb index bff537d3c5..47d0042519 100644 --- a/activerecord/lib/active_record/associations/has_one_association.rb +++ b/activerecord/lib/active_record/associations/has_one_association.rb @@ -8,7 +8,7 @@ module ActiveRecord reflection.klass.transaction do if target && target != record - remove_target!(reflection.options[:dependent]) + remove_target!(options[:dependent]) end if record @@ -29,7 +29,7 @@ module ActiveRecord protected def association_scope - super.order(reflection.options[:order]) + super.order(options[:order]) end private diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index 3ff63656fb..f8da0c5de7 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -3,6 +3,8 @@ module ActiveRecord module Associations module ThroughAssociation #:nodoc: + delegate :source_options, :through_options, :to => :reflection + protected def target_scope @@ -12,8 +14,8 @@ module ActiveRecord def association_scope scope = super.joins(construct_joins) scope = add_conditions(scope) - unless reflection.options[:include] - scope = scope.includes(reflection.source_reflection.options[:include]) + unless options[:include] + scope = scope.includes(source_options[:include]) end scope end @@ -50,17 +52,17 @@ module ActiveRecord reflection_primary_key = reflection.source_reflection.association_primary_key source_primary_key = reflection.source_reflection.foreign_key - if reflection.options[:source_type] + if options[:source_type] column = reflection.source_reflection.foreign_type conditions << - right[column].eq(reflection.options[:source_type]) + right[column].eq(options[:source_type]) end else reflection_primary_key = reflection.source_reflection.foreign_key source_primary_key = reflection.source_reflection.active_record_primary_key - if reflection.source_reflection.options[:as] - column = "#{reflection.source_reflection.options[:as]}_type" + if source_options[:as] + column = "#{source_options[:as]}_type" conditions << left[column].eq(reflection.through_reflection.klass.name) end @@ -98,7 +100,7 @@ module ActiveRecord } } - if reflection.options[:source_type] + if options[:source_type] join_attributes[reflection.source_reflection.foreign_type] = records.map { |record| record.class.base_class.name } end @@ -119,14 +121,14 @@ module ActiveRecord scope = scope.where(reflection.through_reflection.klass.send(:type_condition)) end - scope = scope.where(interpolate(reflection.source_reflection.options[:conditions])) + scope = scope.where(interpolate(source_options[:conditions])) scope.where(through_conditions) end # If there is a hash of conditions then we make sure the keys are scoped to the # through table name if left ambiguous. def through_conditions - conditions = interpolate(reflection.through_reflection.options[:conditions]) + conditions = interpolate(through_options[:conditions]) if conditions.is_a?(Hash) Hash[conditions.map { |key, value| diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 4093a1a209..49659b3aa5 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -394,6 +394,14 @@ module ActiveRecord @source_reflection_names ||= (options[:source] ? [options[:source]] : [name.to_s.singularize, name]).collect { |n| n.to_sym } end + def source_options + source_reflection.options + end + + def through_options + through_reflection.options + end + def association_primary_key source_reflection.association_primary_key end |