Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 9231

Show
Ignore:
Timestamp:
04/06/08 02:18:42 (8 months ago)
Author:
pratik
Message:

Remove duplicate code from associations. [Pratik]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r9230 r9231  
    11*SVN* 
     2 
     3* Remove duplicate code from associations. [Pratik] 
    24 
    35* 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  
    44  module Associations 
    55    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       
    651      def to_ary 
    752        load_target 
     
    3176          flatten_deeper(records).each do |record| 
    3277            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 
    3781          end 
    3882        end 
     
    64108        records = flatten_deeper(records) 
    65109        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           end 
    72         end 
    73         return if records.empty? 
    74110         
    75111        @owner.transaction do 
    76112          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           
    78117          records.each do |record| 
    79118            @target.delete(record) 
     
    181220 
    182221      protected 
     222        def construct_find_options!(options) 
     223        end 
     224         
    183225        def load_target 
    184226          if !@owner.new_record? || foreign_key_present 
  • trunk/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb

    r9230 r9231  
    22  module Associations 
    33    class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc: 
    4       def initialize(owner, reflection) 
    5         super 
    6         construct_sql 
    7       end 
    8  
    94      def create(attributes = {}) 
    105        create_record(attributes) { |record| insert_record(record) } 
     
    1510      end 
    1611 
    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) 
    4414          options[:joins]      = @join_sql 
    4515          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] || '*') 
    6017        end 
    61       end 
    62  
    63       protected 
     18         
    6419        def count_records 
    6520          load_target.size 
  • trunk/activerecord/lib/active_record/associations/has_many_association.rb

    r9230 r9231  
    22  module Associations 
    33    class HasManyAssociation < AssociationCollection #:nodoc: 
    4       def initialize(owner, reflection) 
    5         super 
    6         construct_sql 
    7       end 
    8  
    94      # Count the number of associated records. All arguments are optional. 
    105      def count(*args) 
     
    2116 
    2217          @reflection.klass.count(column_name, options) 
    23         end 
    24       end 
    25  
    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 == 1 
    35             id = ids.first 
    36             record = load_target.detect { |r| id == r.id } 
    37             expects_array ? [ record ] : record 
    38           else 
    39             load_target.select { |r| ids.include?(r.id) } 
    40           end 
    41         else 
    42           conditions = "#{@finder_sql}" 
    43           if sanitized_conditions = sanitize_sql(options[:conditions]) 
    44             conditions << " AND (#{sanitized_conditions})" 
    45           end 
    46           options[:conditions] = conditions 
    47  
    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           end 
    53  
    54           merge_options_from_reflection!(options) 
    55  
    56           # Pass through args exactly as we received them. 
    57           args << options 
    58           @reflection.klass.find(*args) 
    5918        end 
    6019      end 
  • trunk/activerecord/lib/active_record/associations/has_many_through_association.rb

    r9230 r9231  
    33    class HasManyThroughAssociation < HasManyAssociation #:nodoc: 
    44      def initialize(owner, reflection) 
     5        reflection.check_validity! 
    56        super 
    6         reflection.check_validity! 
    7         @finder_sql = construct_conditions 
    8       end 
    9  
    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         end 
    18         options[:conditions] = conditions 
    19  
    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         end 
    25  
    26         options[:select]  = construct_select(options[:select]) 
    27         options[:from]  ||= construct_from 
    28         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 << options 
    35         @reflection.klass.find(*args) 
    367      end 
    378 
     
    6031        return count 
    6132      end 
    62  
    63       # Calculate sum using SQL, not Enumerable 
    64       def sum(*args) 
    65         if block_given? 
    66           calculate(:sum, *args) { |*block_args| yield(*block_args) } 
    67         else 
    68           calculate(:sum, *args) 
    69         end 
    70       end 
    7133       
    7234      def count(*args) 
     
    8042      end 
    8143 
    82  
    8344      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         
    8452        def insert_record(record, force=true) 
    8553          if record.new_record? 
     
    9967          records.each do |associate| 
    10068            klass.delete_all(construct_join_attributes(associate)) 
    101           end 
    102         end 
    103  
    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             else 
    109               super 
    110             end 
    111           elsif @reflection.klass.scopes.include?(method) 
    112             @reflection.klass.scopes[method].call(self, *args) 
    113           else 
    114             with_scope construct_scope do 
    115               if block_given? 
    116                 @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) } 
    117               else 
    118                 @reflection.klass.send(method, *args) 
    119               end 
    120             end 
    12169          end 
    12270        end 
     
    238186              @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{@owner.quoted_id}" 
    239187              @finder_sql << " AND (#{conditions})" if conditions 
     188            else 
     189              @finder_sql = construct_conditions 
    240190          end 
    241191 
  • trunk/activerecord/lib/active_record/associations/has_one_through_association.rb

    r9067 r9231  
    11module ActiveRecord 
    22  module Associations 
    3     class HasOneThroughAssociation < ActiveRecord::Associations::HasManyThroughAssociation 
     3    class HasOneThroughAssociation < HasManyThroughAssociation 
    44       
    55      def create_through_record(new_value) #nodoc: