Permalink
Browse files

Delegate Association#options to the reflection, and replace 'reflecti…

…on.options' with 'options'. Also add through_options and source_options methods for through associations.
  • Loading branch information...
jonleighton authored and tenderlove committed Feb 20, 2011
1 parent 73ff007 commit 32eef69dc1abbf9b67de780a882754e1717c2a3b
@@ -99,12 +99,12 @@ def construct_scope
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 @@ def interpolate(sql, record = nil)
end
def select_value
- reflection.options[:select]
+ options[:select]
end
# Implemented by (some) subclasses
@@ -191,8 +191,8 @@ def construct_owner_attributes(reflection = reflection)
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
@@ -56,7 +56,7 @@ def invertible_for?(record)
end
def target_id
- if reflection.options[:primary_key]
+ if options[:primary_key]
owner.send(reflection.name).try(:id)
else
owner[reflection.foreign_key]
@@ -47,7 +47,7 @@ def select(select = nil)
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 @@ def sum(*args)
# 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 @@ def count(column_name = nil, options = {})
# 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 @@ def destroy(*records)
# 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 @@ def include?(record)
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 @@ def add_to_target(record)
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 @@ def select_value
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 @@ def fetch_first_or_last_using_find?(args)
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
@@ -12,8 +12,8 @@ def initialize(owner, reflection)
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 @@ def count_records
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
@@ -29,7 +29,7 @@ def insert_record(record, validate = true)
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 @@ def count_records
# 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)
@@ -8,7 +8,7 @@ def replace(record, save = true)
reflection.klass.transaction do
if target && target != record
- remove_target!(reflection.options[:dependent])
+ remove_target!(options[:dependent])
end
if record
@@ -29,7 +29,7 @@ def replace(record, save = true)
protected
def association_scope
- super.order(reflection.options[:order])
+ super.order(options[:order])
end
private
@@ -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 @@ def target_scope
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 @@ def construct_joins
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 @@ def construct_join_attributes(*records)
}
}
- 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 @@ def add_conditions(scope)
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|
@@ -394,6 +394,14 @@ def source_reflection_names
@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

0 comments on commit 32eef69

Please sign in to comment.