From a9a53b872944a3582eba167300948e4714412304 Mon Sep 17 00:00:00 2001 From: John Wood Date: Fri, 19 Jun 2009 11:00:52 -0500 Subject: [PATCH] Added more tests for Collection module, cleaned up the code as well. --- lib/couchrest/mixins/collection.rb | 43 +++++++++---- spec/couchrest/more/extended_doc_view_spec.rb | 63 ++++++++++++++++--- 2 files changed, 85 insertions(+), 21 deletions(-) diff --git a/lib/couchrest/mixins/collection.rb b/lib/couchrest/mixins/collection.rb index f590ef3..ab0c7eb 100644 --- a/lib/couchrest/mixins/collection.rb +++ b/lib/couchrest/mixins/collection.rb @@ -7,12 +7,23 @@ module CouchRest end module ClassMethods + + # Creates a new class method, find_all_ on the class + # that will execute the view specified in the collection_options, + # along with all view options specified. This method will return the + # results of the view as an Array of objects which are instances of the + # class. + # + # This method is handy for objects that do not use the view_by method + # to declare their views. + # def provides_collection(collection_name, collection_options) class_eval <<-END, __FILE__, __LINE__ + 1 def self.find_all_#{collection_name}(options = {}) - view_name = "#{collection_options[:through][:view_name]}" - view_options = #{collection_options[:through][:view_options].inspect} || {} - CollectionProxy.new(@database, view_name, view_options.merge(options), Kernel.const_get('#{self}')) + design_doc = "#{collection_options[:through].delete(:design_doc)}" + view_name = "#{collection_options[:through].delete(:view_name)}" + view_options = #{collection_options[:through].inspect} || {} + CollectionProxy.new(@database, design_doc, view_name, view_options.merge(options), Kernel.const_get('#{self}')) end END end @@ -35,7 +46,7 @@ module CouchRest private def create_collection_proxy(options) - view_name, view_options, design_doc = parse_view_options(options) + design_doc, view_name, view_options = parse_view_options(options) CollectionProxy.new(@database, design_doc, view_name, view_options, self) end @@ -46,11 +57,12 @@ module CouchRest view_name = options.delete(:view_name) raise ArgumentError, 'view_name is required' if view_name.nil? - view_options = options.delete(:view_options) || {} - default_view_options = (design_doc['views'][view_name.to_s] && design_doc['views'][view_name.to_s]["couchrest-defaults"]) || {} - view_options = default_view_options.merge(view_options).merge(options) + default_view_options = (design_doc.class == Design && + design_doc['views'][view_name.to_s] && + design_doc['views'][view_name.to_s]["couchrest-defaults"]) || {} + view_options = default_view_options.merge(options) - [view_name, view_options, design_doc] + [design_doc, view_name, view_options] end end @@ -58,13 +70,18 @@ module CouchRest alias_method :proxy_respond_to?, :respond_to? instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ } + DEFAULT_PAGE = 1 + DEFAULT_PER_PAGE = 30 + def initialize(database, design_doc, view_name, view_options = {}, container_class = nil) raise ArgumentError, "database is a required parameter" if database.nil? @database = database - @view_options = view_options @container_class = container_class + strip_pagination_options(view_options) + @view_options = view_options + if design_doc.class == Design @view_name = "#{design_doc.name}/#{view_name}" else @@ -153,10 +170,14 @@ module CouchRest end def parse_options(options) - page = options[:page] || 1 - per_page = options[:per_page] || 30 + page = options.delete(:page) || DEFAULT_PAGE + per_page = options.delete(:per_page) || DEFAULT_PER_PAGE [page.to_i, per_page.to_i] end + + def strip_pagination_options(options) + parse_options(options) + end end end diff --git a/spec/couchrest/more/extended_doc_view_spec.rb b/spec/couchrest/more/extended_doc_view_spec.rb index bfaa2c4..1bdc58d 100644 --- a/spec/couchrest/more/extended_doc_view_spec.rb +++ b/spec/couchrest/more/extended_doc_view_spec.rb @@ -348,7 +348,7 @@ describe "ExtendedDocument views" do a.save end end - it "should return an array of 7 Article objects" do + it "should return a proxy that looks like an array of 7 Article objects" do articles = Article.by_date :key => Date.today articles.class.should == Array articles.size.should == 7 @@ -359,15 +359,58 @@ describe "ExtendedDocument views" do articles.paginate(:page => 2, :per_page => 3).size.should == 3 articles.paginate(:page => 3, :per_page => 3).size.should == 1 end -# it "should get all articles, a few at a time, using paginated each" do -# -# end -# it "should provide a class method to access the collection directly" do -# -# end -# it "should provide class methods for pagination" do -# -# end + it "should get all articles, a few at a time, using paginated each" do + articles = Article.by_date :key => Date.today + articles.paginated_each(:per_page => 3) do |a| + a.should_not be_nil + end + end + it "should provide a class method to access the collection directly" do + articles = Article.collection_proxy_for('Article', 'by_date', :descending => true, + :key => Date.today, :include_docs => true) + articles.class.should == Array + articles.size.should == 7 + end + it "should provide a class method for paginate" do + articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date', + :per_page => 3, :descending => true, :key => Date.today, :include_docs => true) + articles.size.should == 3 + + articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date', + :per_page => 3, :page => 2, :descending => true, :key => Date.today, :include_docs => true) + articles.size.should == 3 + + articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date', + :per_page => 3, :page => 3, :descending => true, :key => Date.today, :include_docs => true) + articles.size.should == 1 + end + it "should provide a class method for paginated_each" do + options = { :design_doc => 'Article', :view_name => 'by_date', + :per_page => 3, :page => 1, :descending => true, :key => Date.today, + :include_docs => true } + Article.paginated_each(options) do |a| + a.should_not be_nil + end + end + it "should provide a class method to get a collection for a view" do + class Article + provides_collection :article_details, :through => { + :design_doc => 'Article', :view_name => 'by_date', :descending => true, + :include_docs => true } + end + + articles = Article.find_all_article_details(:key => Date.today) + articles.class.should == Array + articles.size.should == 7 + end + it "should raise an exception if design_doc is not provided" do + lambda{Article.collection_proxy_for(nil, 'by_date')}.should raise_error + lambda{Article.paginate(:view_name => 'by_date')}.should raise_error + end + it "should raise an exception if view_name is not provided" do + lambda{Article.collection_proxy_for('Article', nil)}.should raise_error + lambda{Article.paginate(:design_doc => 'Article')}.should raise_error + end end end