Skip to content
Browse files

Implement #many? for NamedScope and AssociationCollection using #size [

…#1500 state:resolved]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
  • Loading branch information...
1 parent 11bac70 commit 4e8c36a7417e5d447c9b15d5c61df0c014ee6d3b @chrisk chrisk committed with lifo Mar 16, 2009
View
2 activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Implement #many? for NamedScope and AssociationCollection using #size. #1500 [Chris Kampmeier]
+
* Added :touch option to belongs_to associations that will touch the parent record when the current record is saved or destroyed [DHH]
* Added ActiveRecord::Base#touch to update the updated_at/on attributes (or another specified timestamp) with the current time [DHH]
View
9 activerecord/lib/active_record/associations/association_collection.rb
@@ -302,6 +302,15 @@ def any?
end
end
+ # Returns true if the collection has more than 1 record. Equivalent to collection.size > 1.
+ def many?
+ if block_given?
+ method_missing(:many?) { |*block_args| yield(*block_args) }
+ else
+ size > 1
+ end
+ end
+
def uniq(collection = self)
seen = Set.new
collection.inject([]) do |kept, record|
View
11 activerecord/lib/active_record/named_scope.rb
@@ -109,7 +109,7 @@ def named_scope(name, options = {}, &block)
class Scope
attr_reader :proxy_scope, :proxy_options, :current_scoped_methods_when_defined
- NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? respond_to?).to_set
+ NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? many? respond_to?).to_set
[].methods.each do |m|
unless m =~ /^__/ || NON_DELEGATE_METHODS.include?(m.to_s)
delegate m, :to => :proxy_found
@@ -168,6 +168,15 @@ def any?
end
end
+ # Returns true if the named scope has more than 1 matching record.
+ def many?
+ if block_given?
+ proxy_found.many? { |*block_args| yield(*block_args) }
+ else
+ size > 1
+ end
+ end
+
protected
def proxy_found
@found || load_found
View
39 activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1023,6 +1023,45 @@ def test_calling_first_or_last_with_integer_on_association_should_load_associati
assert firm.clients.loaded?
end
+ def test_calling_many_should_count_instead_of_loading_association
+ firm = companies(:first_firm)
+ assert_queries(1) do
+ firm.clients.many? # use count query
+ end
+ assert !firm.clients.loaded?
+ end
+
+ def test_calling_many_on_loaded_association_should_not_use_query
+ firm = companies(:first_firm)
+ firm.clients.collect # force load
+ assert_no_queries { assert firm.clients.many? }
+ end
+
+ def test_calling_many_should_defer_to_collection_if_using_a_block
+ firm = companies(:first_firm)
+ assert_queries(1) do
+ firm.clients.expects(:size).never
+ firm.clients.many? { true }
+ end
+ assert firm.clients.loaded?
+ end
+
+ def test_calling_many_should_return_false_if_none_or_one
+ firm = companies(:another_firm)
+ assert !firm.clients_like_ms.many?
+ assert_equal 0, firm.clients_like_ms.size
+
+ firm = companies(:first_firm)
+ assert !firm.limited_clients.many?
+ assert_equal 1, firm.limited_clients.size
+ end
+
+ def test_calling_many_should_return_true_if_more_than_one
+ firm = companies(:first_firm)
+ assert firm.clients.many?
+ assert_equal 2, firm.clients.size
+ end
+
def test_joins_with_namespaced_model_should_use_correct_type
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = true
View
34 activerecord/test/cases/named_scope_test.rb
@@ -235,6 +235,40 @@ def test_any_should_not_fire_query_if_named_scope_loaded
assert_no_queries { assert topics.any? }
end
+ def test_many_should_not_load_results
+ topics = Topic.base
+ assert_queries(2) do
+ topics.many? # use count query
+ topics.collect # force load
+ topics.many? # use loaded (no query)
+ end
+ end
+
+ def test_many_should_call_proxy_found_if_using_a_block
+ topics = Topic.base
+ assert_queries(1) do
+ topics.expects(:size).never
+ topics.many? { true }
+ end
+ end
+
+ def test_many_should_not_fire_query_if_named_scope_loaded
+ topics = Topic.base
+ topics.collect # force load
+ assert_no_queries { assert topics.many? }
+ end
+
+ def test_many_should_return_false_if_none_or_one
+ topics = Topic.base.scoped(:conditions => {:id => 0})
+ assert !topics.many?
+ topics = Topic.base.scoped(:conditions => {:id => 1})
+ assert !topics.many?
+ end
+
+ def test_many_should_return_true_if_more_than_one
+ assert Topic.base.many?
+ end
+
def test_should_build_with_proxy_options
topic = Topic.approved.build({})
assert topic.approved

0 comments on commit 4e8c36a

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