Added more tests for Collection module, cleaned up the code as well.

This commit is contained in:
John Wood 2009-06-19 11:00:52 -05:00 committed by Matt Aimonetti
parent 5963f1d4f8
commit a9a53b8729
2 changed files with 85 additions and 21 deletions

View file

@ -7,12 +7,23 @@ module CouchRest
end end
module ClassMethods module ClassMethods
# Creates a new class method, find_all_<collection_name> 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) def provides_collection(collection_name, collection_options)
class_eval <<-END, __FILE__, __LINE__ + 1 class_eval <<-END, __FILE__, __LINE__ + 1
def self.find_all_#{collection_name}(options = {}) def self.find_all_#{collection_name}(options = {})
view_name = "#{collection_options[:through][:view_name]}" design_doc = "#{collection_options[:through].delete(:design_doc)}"
view_options = #{collection_options[:through][:view_options].inspect} || {} view_name = "#{collection_options[:through].delete(:view_name)}"
CollectionProxy.new(@database, view_name, view_options.merge(options), Kernel.const_get('#{self}')) view_options = #{collection_options[:through].inspect} || {}
CollectionProxy.new(@database, design_doc, view_name, view_options.merge(options), Kernel.const_get('#{self}'))
end end
END END
end end
@ -35,7 +46,7 @@ module CouchRest
private private
def create_collection_proxy(options) 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) CollectionProxy.new(@database, design_doc, view_name, view_options, self)
end end
@ -46,11 +57,12 @@ module CouchRest
view_name = options.delete(:view_name) view_name = options.delete(:view_name)
raise ArgumentError, 'view_name is required' if view_name.nil? raise ArgumentError, 'view_name is required' if view_name.nil?
view_options = options.delete(:view_options) || {} default_view_options = (design_doc.class == Design &&
default_view_options = (design_doc['views'][view_name.to_s] && design_doc['views'][view_name.to_s]["couchrest-defaults"]) || {} design_doc['views'][view_name.to_s] &&
view_options = default_view_options.merge(view_options).merge(options) 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
end end
@ -58,13 +70,18 @@ module CouchRest
alias_method :proxy_respond_to?, :respond_to? alias_method :proxy_respond_to?, :respond_to?
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ } 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) def initialize(database, design_doc, view_name, view_options = {}, container_class = nil)
raise ArgumentError, "database is a required parameter" if database.nil? raise ArgumentError, "database is a required parameter" if database.nil?
@database = database @database = database
@view_options = view_options
@container_class = container_class @container_class = container_class
strip_pagination_options(view_options)
@view_options = view_options
if design_doc.class == Design if design_doc.class == Design
@view_name = "#{design_doc.name}/#{view_name}" @view_name = "#{design_doc.name}/#{view_name}"
else else
@ -153,10 +170,14 @@ module CouchRest
end end
def parse_options(options) def parse_options(options)
page = options[:page] || 1 page = options.delete(:page) || DEFAULT_PAGE
per_page = options[:per_page] || 30 per_page = options.delete(:per_page) || DEFAULT_PER_PAGE
[page.to_i, per_page.to_i] [page.to_i, per_page.to_i]
end end
def strip_pagination_options(options)
parse_options(options)
end
end end
end end

View file

@ -348,7 +348,7 @@ describe "ExtendedDocument views" do
a.save a.save
end end
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 = Article.by_date :key => Date.today
articles.class.should == Array articles.class.should == Array
articles.size.should == 7 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 => 2, :per_page => 3).size.should == 3
articles.paginate(:page => 3, :per_page => 3).size.should == 1 articles.paginate(:page => 3, :per_page => 3).size.should == 1
end end
# it "should get all articles, a few at a time, using paginated each" do it "should get all articles, a few at a time, using paginated each" do
# articles = Article.by_date :key => Date.today
# end articles.paginated_each(:per_page => 3) do |a|
# it "should provide a class method to access the collection directly" do a.should_not be_nil
# end
# end end
# it "should provide class methods for pagination" do it "should provide a class method to access the collection directly" do
# articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
# end :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
end end