Permalink
Browse files

insert ScopedFinder as a proxy in Document#all

  • Loading branch information...
fauxparse committed Jan 31, 2010
1 parent cf5c8cd commit cf3dd56b0f94b82b90200165b70a275e5835110d
View
@@ -104,6 +104,7 @@ def self.normalize_object_id(value)
require 'mongo_mapper/finder_options'
require 'mongo_mapper/dynamic_finder'
require 'mongo_mapper/descendant_appends'
+require 'mongo_mapper/scoped_finder'
require 'mongo_mapper/plugins'
require 'mongo_mapper/plugins/associations'
@@ -95,7 +95,11 @@ def last(options={})
end
def all(options={})
- find_many(options)
+ ScopedFinder.new(self, options)
+ end
+
+ def scoped(options={})
+ all(options)
end
def count(options={})
@@ -16,13 +16,13 @@ def self.normalized_order_direction(direction)
end
def initialize(model, options)
- raise ArgumentError, "Options must be a hash" unless options.is_a?(Hash)
+ raise ArgumentError, "Options must be a hash" unless options.respond_to?(:to_hash)
@model = model
@options = {}
@conditions = {}
- options.each_pair do |key, value|
+ options.to_hash.each_pair do |key, value|
key = key.respond_to?(:to_sym) ? key.to_sym : key
if OptionKeys.include?(key)
@options[key] = value
@@ -53,6 +53,10 @@ def to_a
[criteria, options]
end
+ def to_hash
+ criteria.merge options
+ end
+
def compose(other)
return other.dup if criteria.empty? && options.empty?
@@ -74,6 +78,13 @@ def compose(other)
self.class.new(@model, hash)
end
+
+ def merge(other)
+ case other
+ when FinderOptions then compose(other)
+ else compose FinderOptions.new(@model, other)
+ end
+ end
private
def to_mongo_criteria(conditions, parent_key=nil)
@@ -0,0 +1,61 @@
+module MongoMapper
+ class ScopedFinder
+ include Enumerable
+
+ attr_reader :model, :options
+
+ delegate :[], :each, :to_a, :to => :records
+
+ def initialize(model, options = {})
+ @model = model
+ @options = FinderOptions.new(@model, options)
+ end
+
+ def proxy_options
+ @proxy_options ||= options.to_hash
+ end
+
+ def records
+ @records ||= model.send :find_many, proxy_options
+ end
+ alias :to_a :records
+
+ def count
+ @count ||= model.count(options.to_hash)
+ end
+ alias :size :count
+
+ def empty?
+ if @records
+ @records.empty?
+ else
+ count == 0
+ end
+ end
+
+ def ==(other)
+ case other
+ when ScopedFinder
+ @model == other.model && proxy_options == other.proxy_options
+ else
+ records == other
+ end
+ end
+
+ def all(options = {})
+ if options.empty?
+ self
+ else
+ scoped(options)
+ end
+ end
+
+ def scoped(options = {})
+ self.class.new model, @options.compose(FinderOptions.new(model, options))
+ end
+
+ def method_missing(method, *args)
+ records.send method, *args
+ end
+ end
+end
@@ -361,7 +361,7 @@ def setup
should "find all documents based on arguments" do
docs = @document.find_all_by_last_name('Nunemaker')
- docs.should be_kind_of(Array)
+ # docs.should be_kind_of(Array)
docs.should include(@doc1)
docs.should include(@doc3)
end
@@ -237,7 +237,7 @@ def expects_one_query
@person_class.identity_map.clear
people = @person_class.find(person1.id, person2.id, person3.id)
- assert_in_map(people)
+ assert_in_map(people.to_a)
end
should "add missing documents to map and return existing ones" do
@@ -304,7 +304,7 @@ def expects_one_query
@person_class.identity_map.clear
people = @person_class.all(:_id => [person1.id, person2.id, person3.id])
- assert_in_map(people)
+ assert_in_map(people.to_a)
end
should "add missing documents to map and return existing ones" do
@@ -469,7 +469,7 @@ class ::BlogPost < ::Item
post2 = @post_class.create(:title => 'Bar')
@post_class.identity_map.clear
- assert_not_in_map(@post_class.all)
+ assert_not_in_map(@post_class.all.to_a)
end
end
end
@@ -0,0 +1,21 @@
+require 'test_helper'
+require 'models'
+
+class ScopedFinderTest < Test::Unit::TestCase
+ include MongoMapper
+
+ context "from #all" do
+ should "be the right class" do
+ PostComment.all.class.should == ScopedFinder
+ end
+
+ should "retain options" do
+ PostComment.all(:foo => "bar").proxy_options.should == { :foo => "bar", :limit => 0, :fields => nil, :skip => 0, :sort => nil }
+ end
+
+ should "compose options with scoped" do
+ PostComment.all(:foo => "bar").scoped(:baz => "qux").proxy_options.should ==
+ { :foo => "bar", :baz => "qux", :limit => 0, :fields => nil, :skip => 0, :sort => nil }
+ end
+ end
+end

0 comments on commit cf3dd56

Please sign in to comment.