Skip to content
This repository
Browse code

Nullify the relation at a more general level.

This allows us to avoid hacks like the "return 0 if owner.new_record?"
in #count (which this commit removes).

Also, the relevant foreign key may actually be present even on a new
owner record, in which case we *don't* want a null relation. This logic
is encapsulated in the #null_scope? method.

We also need to make sure that the CollectionProxy is not 'infected'
with the NullRelation module, or else the methods from there will
override the definitions in CollectionProxy, leading to incorrect
results. Hence the nullify: false option to CollectionAssociation#scope.
(This feels a bit nasty but I can't think of a better way.)
  • Loading branch information...
commit aae4f357b5dae389b91129258f9d6d3043e7631e 1 parent 6710f05
Jon Leighton authored November 09, 2012
12  activerecord/lib/active_record/associations/collection_association.rb
@@ -174,8 +174,6 @@ def sum(*args)
174 174
       # association, it will be used for the query. Otherwise, construct options and pass them with
175 175
       # scope to the target class's +count+.
176 176
       def count(column_name = nil, count_options = {})
177  
-        return 0 if owner.new_record?
178  
-
179 177
         column_name, count_options = nil, column_name if column_name.is_a?(Hash)
180 178
 
181 179
         if options[:counter_sql] || options[:finder_sql]
@@ -366,6 +364,16 @@ def add_to_target(record)
366 364
         record
367 365
       end
368 366
 
  367
+      def scope(opts = {})
  368
+        scope = super()
  369
+        scope.none! if opts.fetch(:nullify, true) && null_scope?
  370
+        scope
  371
+      end
  372
+
  373
+      def null_scope?
  374
+        owner.new_record? && !foreign_key_present?
  375
+      end
  376
+
369 377
       private
370 378
 
371 379
         def custom_counter_sql
7  activerecord/lib/active_record/associations/collection_proxy.rb
@@ -31,7 +31,7 @@ class CollectionProxy < Relation
31 31
       def initialize(association) #:nodoc:
32 32
         @association = association
33 33
         super association.klass, association.klass.arel_table
34  
-        merge! association.scope
  34
+        merge! association.scope(nullify: false)
35 35
       end
36 36
 
37 37
       def target
@@ -835,9 +835,8 @@ def scoping
835 835
       # Returns a <tt>Relation</tt> object for the records in this association
836 836
       def scope
837 837
         association = @association
838  
-        scope = @association.scope
839  
-        scope.none! if @association.owner.new_record?
840  
-        scope.extending! do
  838
+
  839
+        @association.scope.extending! do
841 840
           define_method(:proxy_association) { association }
842 841
         end
843 842
       end
2  activerecord/lib/active_record/null_relation.rb
@@ -46,7 +46,7 @@ def where_values_hash
46 46
       {}
47 47
     end
48 48
 
49  
-    def count
  49
+    def count(*)
50 50
       0
51 51
     end
52 52
 

0 notes on commit aae4f35

Please sign in to comment.
Something went wrong with that request. Please try again.