Changeset 9231
- Timestamp:
- 04/06/08 02:18:42 (5 months ago)
- Files:
-
- trunk/activerecord/CHANGELOG (modified) (1 diff)
- trunk/activerecord/lib/active_record/associations/association_collection.rb (modified) (4 diffs)
- trunk/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb (modified) (2 diffs)
- trunk/activerecord/lib/active_record/associations/has_many_association.rb (modified) (2 diffs)
- trunk/activerecord/lib/active_record/associations/has_many_through_association.rb (modified) (5 diffs)
- trunk/activerecord/lib/active_record/associations/has_one_through_association.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activerecord/CHANGELOG
r9230 r9231 1 1 *SVN* 2 3 * Remove duplicate code from associations. [Pratik] 2 4 3 5 * Refactor HasManyThroughAssociation to inherit from HasManyAssociation. Association callbacks and <association>_ids= now work with hm:t. #11516 [rubyruy] trunk/activerecord/lib/active_record/associations/association_collection.rb
r9230 r9231 4 4 module Associations 5 5 class AssociationCollection < AssociationProxy #:nodoc: 6 def initialize(owner, reflection) 7 super 8 construct_sql 9 end 10 11 def find(*args) 12 options = args.extract_options! 13 14 # If using a custom finder_sql, scan the entire collection. 15 if @reflection.options[:finder_sql] 16 expects_array = args.first.kind_of?(Array) 17 ids = args.flatten.compact.uniq.map(&:to_i) 18 19 if ids.size == 1 20 id = ids.first 21 record = load_target.detect { |r| id == r.id } 22 expects_array ? [ record ] : record 23 else 24 load_target.select { |r| ids.include?(r.id) } 25 end 26 else 27 conditions = "#{@finder_sql}" 28 if sanitized_conditions = sanitize_sql(options[:conditions]) 29 conditions << " AND (#{sanitized_conditions})" 30 end 31 32 options[:conditions] = conditions 33 34 if options[:order] && @reflection.options[:order] 35 options[:order] = "#{options[:order]}, #{@reflection.options[:order]}" 36 elsif @reflection.options[:order] 37 options[:order] = @reflection.options[:order] 38 end 39 40 # Build options specific to association 41 construct_find_options!(options) 42 43 merge_options_from_reflection!(options) 44 45 # Pass through args exactly as we received them. 46 args << options 47 @reflection.klass.find(*args) 48 end 49 end 50 6 51 def to_ary 7 52 load_target … … 31 76 flatten_deeper(records).each do |record| 32 77 raise_on_type_mismatch(record) 33 callback(:before_add, record) 34 result &&= insert_record(record) unless @owner.new_record? 35 @target << record 36 callback(:after_add, record) 78 add_record_to_target_with_callbacks(record) do |r| 79 result &&= insert_record(record) unless @owner.new_record? 80 end 37 81 end 38 82 end … … 64 108 records = flatten_deeper(records) 65 109 records.each { |record| raise_on_type_mismatch(record) } 66 records.reject! do |record|67 if record.new_record?68 callback(:before_remove, record)69 @target.delete(record)70 callback(:after_remove, record)71 end72 end73 return if records.empty?74 110 75 111 @owner.transaction do 76 112 records.each { |record| callback(:before_remove, record) } 77 delete_records(records) 113 114 old_records = records.reject {|r| r.new_record? } 115 delete_records(old_records) if old_records.any? 116 78 117 records.each do |record| 79 118 @target.delete(record) … … 181 220 182 221 protected 222 def construct_find_options!(options) 223 end 224 183 225 def load_target 184 226 if !@owner.new_record? || foreign_key_present trunk/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
r9230 r9231 2 2 module Associations 3 3 class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc: 4 def initialize(owner, reflection)5 super6 construct_sql7 end8 9 4 def create(attributes = {}) 10 5 create_record(attributes) { |record| insert_record(record) } … … 15 10 end 16 11 17 def find_first 18 load_target.first 19 end 20 21 def find(*args) 22 options = args.extract_options! 23 24 # If using a custom finder_sql, scan the entire collection. 25 if @reflection.options[:finder_sql] 26 expects_array = args.first.kind_of?(Array) 27 ids = args.flatten.compact.uniq 28 29 if ids.size == 1 30 id = ids.first.to_i 31 record = load_target.detect { |r| id == r.id } 32 expects_array ? [record] : record 33 else 34 load_target.select { |r| ids.include?(r.id) } 35 end 36 else 37 conditions = "#{@finder_sql}" 38 39 if sanitized_conditions = sanitize_sql(options[:conditions]) 40 conditions << " AND (#{sanitized_conditions})" 41 end 42 43 options[:conditions] = conditions 12 protected 13 def construct_find_options!(options) 44 14 options[:joins] = @join_sql 45 15 options[:readonly] = finding_with_ambiguous_select?(options[:select] || @reflection.options[:select]) 46 47 if options[:order] && @reflection.options[:order] 48 options[:order] = "#{options[:order]}, #{@reflection.options[:order]}" 49 elsif @reflection.options[:order] 50 options[:order] = @reflection.options[:order] 51 end 52 53 merge_options_from_reflection!(options) 54 55 options[:select] ||= (@reflection.options[:select] || '*') 56 57 # Pass through args exactly as we received them. 58 args << options 59 @reflection.klass.find(*args) 16 options[:select] ||= (@reflection.options[:select] || '*') 60 17 end 61 end 62 63 protected 18 64 19 def count_records 65 20 load_target.size trunk/activerecord/lib/active_record/associations/has_many_association.rb
r9230 r9231 2 2 module Associations 3 3 class HasManyAssociation < AssociationCollection #:nodoc: 4 def initialize(owner, reflection)5 super6 construct_sql7 end8 9 4 # Count the number of associated records. All arguments are optional. 10 5 def count(*args) … … 21 16 22 17 @reflection.klass.count(column_name, options) 23 end24 end25 26 def find(*args)27 options = args.extract_options!28 29 # If using a custom finder_sql, scan the entire collection.30 if @reflection.options[:finder_sql]31 expects_array = args.first.kind_of?(Array)32 ids = args.flatten.compact.uniq.map(&:to_i)33 34 if ids.size == 135 id = ids.first36 record = load_target.detect { |r| id == r.id }37 expects_array ? [ record ] : record38 else39 load_target.select { |r| ids.include?(r.id) }40 end41 else42 conditions = "#{@finder_sql}"43 if sanitized_conditions = sanitize_sql(options[:conditions])44 conditions << " AND (#{sanitized_conditions})"45 end46 options[:conditions] = conditions47 48 if options[:order] && @reflection.options[:order]49 options[:order] = "#{options[:order]}, #{@reflection.options[:order]}"50 elsif @reflection.options[:order]51 options[:order] = @reflection.options[:order]52 end53 54 merge_options_from_reflection!(options)55 56 # Pass through args exactly as we received them.57 args << options58 @reflection.klass.find(*args)59 18 end 60 19 end trunk/activerecord/lib/active_record/associations/has_many_through_association.rb
r9230 r9231 3 3 class HasManyThroughAssociation < HasManyAssociation #:nodoc: 4 4 def initialize(owner, reflection) 5 reflection.check_validity! 5 6 super 6 reflection.check_validity!7 @finder_sql = construct_conditions8 end9 10 11 def find(*args)12 options = args.extract_options!13 14 conditions = "#{@finder_sql}"15 if sanitized_conditions = sanitize_sql(options[:conditions])16 conditions << " AND (#{sanitized_conditions})"17 end18 options[:conditions] = conditions19 20 if options[:order] && @reflection.options[:order]21 options[:order] = "#{options[:order]}, #{@reflection.options[:order]}"22 elsif @reflection.options[:order]23 options[:order] = @reflection.options[:order]24 end25 26 options[:select] = construct_select(options[:select])27 options[:from] ||= construct_from28 options[:joins] = construct_joins(options[:joins])29 options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil?30 31 merge_options_from_reflection!(options)32 33 # Pass through args exactly as we received them.34 args << options35 @reflection.klass.find(*args)36 7 end 37 8 … … 60 31 return count 61 32 end 62 63 # Calculate sum using SQL, not Enumerable64 def sum(*args)65 if block_given?66 calculate(:sum, *args) { |*block_args| yield(*block_args) }67 else68 calculate(:sum, *args)69 end70 end71 33 72 34 def count(*args) … … 80 42 end 81 43 82 83 44 protected 45 def construct_find_options!(options) 46 options[:select] = construct_select(options[:select]) 47 options[:from] ||= construct_from 48 options[:joins] = construct_joins(options[:joins]) 49 options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil? 50 end 51 84 52 def insert_record(record, force=true) 85 53 if record.new_record? … … 99 67 records.each do |associate| 100 68 klass.delete_all(construct_join_attributes(associate)) 101 end102 end103 104 def method_missing(method, *args)105 if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))106 if block_given?107 super { |*block_args| yield(*block_args) }108 else109 super110 end111 elsif @reflection.klass.scopes.include?(method)112 @reflection.klass.scopes[method].call(self, *args)113 else114 with_scope construct_scope do115 if block_given?116 @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) }117 else118 @reflection.klass.send(method, *args)119 end120 end121 69 end 122 70 end … … 238 186 @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{@owner.quoted_id}" 239 187 @finder_sql << " AND (#{conditions})" if conditions 188 else 189 @finder_sql = construct_conditions 240 190 end 241 191 trunk/activerecord/lib/active_record/associations/has_one_through_association.rb
r9067 r9231 1 1 module ActiveRecord 2 2 module Associations 3 class HasOneThroughAssociation < ActiveRecord::Associations::HasManyThroughAssociation3 class HasOneThroughAssociation < HasManyThroughAssociation 4 4 5 5 def create_through_record(new_value) #nodoc: