will_paginate_couchrest 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -10,6 +10,10 @@ Automatically generate views with an extra reduce method used to generate the to
10
10
 
11
11
  == History
12
12
 
13
+ 2010-06-26 - 0.3.1 - Minor fix, duplicate view options to avoid ExtendedDocument bug
14
+
15
+ 2010-06-21 - 0.3.0 - Added support for new CouchRest Model
16
+
13
17
  2010-04-05 - 0.2.0 - Added support for CouchRest Proxy class
14
18
 
15
19
  2010-03-05 - 0.1.0 - Initial version
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.1
@@ -1,22 +1,47 @@
1
1
 
2
- require('will_paginate_couchrest/class_methods')
3
- require('will_paginate_couchrest/proxy_methods')
2
+ require 'will_paginate'
3
+ require 'will_paginate_couchrest/class_methods'
4
+ require 'will_paginate_couchrest/proxy_methods'
4
5
 
5
6
  # Take the liberty of adding ourself to the couchrest library
6
7
 
7
- module CouchRest
8
- class ExtendedDocument < Document
9
- include CouchRest::Mixins::WillPaginate
8
+ if defined?(CouchRest::ExtendedDocument)
9
+ module CouchRest
10
+ class ExtendedDocument < Document
11
+ include CouchRest::WillPaginate
12
+ end
13
+ end
14
+
15
+ module CouchRest
16
+ module Mixins
17
+ module ClassProxy
18
+ class Proxy
19
+ include CouchRest::WillPaginate::ProxyMethods
20
+ end
21
+ end
22
+ end
10
23
  end
11
24
  end
12
25
 
13
- module CouchRest
14
- module Mixins
15
- module ClassProxy
16
- class Proxy
17
- include CouchRest::Mixins::WillPaginate::ProxyMethods
26
+ if defined?(CouchRest::Model::Base)
27
+ module CouchRest
28
+ module Model
29
+ class Base < Document
30
+ include CouchRest::WillPaginate
31
+ end
32
+ end
33
+ end
34
+
35
+ module CouchRest
36
+ module Model
37
+ module ClassProxy
38
+ class Proxy
39
+ include CouchRest::WillPaginate::ProxyMethods
40
+ end
18
41
  end
19
42
  end
20
43
  end
21
44
  end
22
45
 
46
+
47
+
@@ -1,147 +1,146 @@
1
1
  module CouchRest
2
- module Mixins
3
- module WillPaginate
2
+ module WillPaginate
4
3
 
5
- def self.included(base)
6
- base.extend(ClassMethods)
7
- end
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
8
7
 
9
- module ClassMethods
10
- # Define a CouchDB will paginate view. The name of the view will be the concatenation
11
- # of <tt>paginate_by</tt> and the keys joined by <tt>_and_</tt>
12
- #
13
- # ==== Example paginated views:
14
- #
15
- # class Post
16
- # # view with default options
17
- # # query with Post.paginate_by_date
18
- # paginated_view_by :date, :descending => true
19
- #
20
- # # view with compound sort-keys
21
- # # query with Post.by_user_id_and_date
22
- # paginated_view_by :user_id, :date
23
- #
24
- # # view with custom map/reduce functions
25
- # # query with Post.by_tags :reduce => true
26
- # paginated_view_by :tags,
27
- # :map =>
28
- # "function(doc) {
29
- # if (doc['couchrest-type'] == 'Post' && doc.tags) {
30
- # doc.tags.forEach(function(tag){
31
- # emit(doc.tag, 1);
32
- # });
33
- # }
34
- # }",
35
- # :reduce =>
36
- # "function(keys, values, rereduce) {
37
- # return sum(values);
38
- # }"
39
- # end
40
- #
41
- # <tt>paginated_view_by :date</tt> will create a view defined by this Javascript
42
- # function:
43
- #
44
- # function(doc) {
45
- # if (doc['couchrest-type'] == 'Post' && doc.date) {
46
- # emit(doc.date, 1);
47
- # }
48
- # }
49
- #
50
- # And a standard summing reduce function like the following:
51
- #
52
- # function(keys, values, rereduce) {
53
- # return sum(values);
54
- # }
55
- #
56
- # It can be queried by calling <tt>Post.paginate_by_date</tt> which accepts all
57
- # valid options for CouchRest::Database#view. In addition, calling with
58
- # the <tt>:raw => true</tt> option will return the view rows
59
- # themselves. By default <tt>Post.by_date</tt> will return the
60
- # documents included in the generated view.
61
- #
62
- # For further details on <tt>view_by</tt>'s other options, please see the
63
- # standard documentation.
64
- def paginated_view_by(*keys)
8
+ module ClassMethods
9
+ # Define a CouchDB will paginate view. The name of the view will be the concatenation
10
+ # of <tt>paginate_by</tt> and the keys joined by <tt>_and_</tt>
11
+ #
12
+ # ==== Example paginated views:
13
+ #
14
+ # class Post
15
+ # # view with default options
16
+ # # query with Post.paginate_by_date
17
+ # paginated_view_by :date, :descending => true
18
+ #
19
+ # # view with compound sort-keys
20
+ # # query with Post.by_user_id_and_date
21
+ # paginated_view_by :user_id, :date
22
+ #
23
+ # # view with custom map/reduce functions
24
+ # # query with Post.by_tags :reduce => true
25
+ # paginated_view_by :tags,
26
+ # :map =>
27
+ # "function(doc) {
28
+ # if (doc['couchrest-type'] == 'Post' && doc.tags) {
29
+ # doc.tags.forEach(function(tag){
30
+ # emit(doc.tag, 1);
31
+ # });
32
+ # }
33
+ # }",
34
+ # :reduce =>
35
+ # "function(keys, values, rereduce) {
36
+ # return sum(values);
37
+ # }"
38
+ # end
39
+ #
40
+ # <tt>paginated_view_by :date</tt> will create a view defined by this Javascript
41
+ # function:
42
+ #
43
+ # function(doc) {
44
+ # if (doc['couchrest-type'] == 'Post' && doc.date) {
45
+ # emit(doc.date, 1);
46
+ # }
47
+ # }
48
+ #
49
+ # And a standard summing reduce function like the following:
50
+ #
51
+ # function(keys, values, rereduce) {
52
+ # return sum(values);
53
+ # }
54
+ #
55
+ # It can be queried by calling <tt>Post.paginate_by_date</tt> which accepts all
56
+ # valid options for CouchRest::Database#view. In addition, calling with
57
+ # the <tt>:raw => true</tt> option will return the view rows
58
+ # themselves. By default <tt>Post.by_date</tt> will return the
59
+ # documents included in the generated view.
60
+ #
61
+ # For further details on <tt>view_by</tt>'s other options, please see the
62
+ # standard documentation.
63
+ def paginated_view_by(*keys)
65
64
 
66
- # Prepare the Traditional view
67
- opts = keys.last.is_a?(Hash) ? keys.pop : {}
68
- view_name = "by_#{keys.join('_and_')}"
69
- method_name = "paginate_#{view_name}"
65
+ # Prepare the Traditional view
66
+ opts = keys.last.is_a?(Hash) ? keys.pop : {}
67
+ view_name = "by_#{keys.join('_and_')}"
68
+ method_name = "paginate_#{view_name}"
70
69
 
71
- doc_keys = keys.collect{|k| "doc['#{k}']"}
72
- key_emit = doc_keys.length == 1 ? "#{doc_keys.first}" : "[#{doc_keys.join(', ')}]"
73
- guards = opts.delete(:guards) || []
74
- guards.push("(doc['couchrest-type'] == '#{self.to_s}')")
75
- guards.concat doc_keys
70
+ doc_keys = keys.collect{|k| "doc['#{k}']"}
71
+ key_emit = doc_keys.length == 1 ? "#{doc_keys.first}" : "[#{doc_keys.join(', ')}]"
72
+ guards = opts.delete(:guards) || []
73
+ guards.push("(doc['couchrest-type'] == '#{self.to_s}')")
74
+ guards.concat doc_keys
76
75
 
77
- opts = {
78
- :map => "
79
- function( doc ) {
80
- if (#{guards.join(' && ')}) {
81
- emit(#{key_emit}, 1 );
82
- }
76
+ opts = {
77
+ :map => "
78
+ function( doc ) {
79
+ if (#{guards.join(' && ')}) {
80
+ emit(#{key_emit}, 1 );
83
81
  }
84
- ",
85
- :reduce => "
86
- function(keys, values, rereduce) {
87
- return sum(values);
88
- }
89
- "
90
- }.merge(opts)
82
+ }
83
+ ",
84
+ :reduce => "
85
+ function(keys, values, rereduce) {
86
+ return sum(values);
87
+ }
88
+ "
89
+ }.merge(opts)
91
90
 
92
- # View prepared, send to traditional view_by
93
- view_by keys, opts
91
+ # View prepared, send to traditional view_by
92
+ view_by keys, opts
94
93
 
95
- instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
96
- def #{method_name}(options = {})
97
- paginated_view('#{view_name}', options)
98
- end
99
- RUBY_EVAL
100
- end
94
+ instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
95
+ def #{method_name}(options = {})
96
+ paginated_view('#{view_name}', options)
97
+ end
98
+ RUBY_EVAL
99
+ end
101
100
 
102
- ##
103
- # Generate a Will Paginate collection from all the available
104
- # documents stored with a matching couchrest-type.
105
- #
106
- # Requires no declaration as the 'all' view is built into couchrest
107
- # Extended Documents.
108
- #
109
- def paginate_all(options = {})
110
- paginated_view(:all, options)
111
- end
101
+ ##
102
+ # Generate a Will Paginate collection from all the available
103
+ # documents stored with a matching couchrest-type.
104
+ #
105
+ # Requires no declaration as the 'all' view is built into couchrest
106
+ # Extended Documents.
107
+ #
108
+ def paginate_all(options = {})
109
+ paginated_view(:all, options)
110
+ end
112
111
 
113
- ##
114
- # Return a WillPaginate collection suitable for usage
115
- #
116
- def paginated_view(view_name, options = {})
117
- raise "Missing per_page parameter" if options[:per_page].nil?
112
+ ##
113
+ # Return a WillPaginate collection suitable for usage
114
+ #
115
+ def paginated_view(view_name, options = {})
116
+ raise "Missing per_page parameter" if options[:per_page].nil?
118
117
 
119
- options[:page] ||= 1
118
+ options[:page] ||= 1
120
119
 
121
- ::WillPaginate::Collection.create( options[:page], options[:per_page] ) do |pager|
122
- # perform view count first (should create designs if missing)
123
- if view_name.to_sym == :all
124
- pager.total_entries = count({:database => options[:database]})
125
- else
126
- total = view( view_name, options.dup.update(:reduce => true) )['rows'].pop
127
- pager.total_entries = total ? total['value'] : 0
128
- end
129
- p_options = options.merge(
130
- :design_doc => self.to_s, :view_name => view_name,
131
- :include_docs => true
132
- )
133
- # Only provide the reduce parameter when necessary. This is when the view has
134
- # been set with a reduce method and requires the reduce boolean parameter
135
- # to be either true or false on all requests.
136
- p_options[:reduce] = false unless view_name.to_sym == :all
137
- results = paginate(p_options)
138
- pager.replace( results )
120
+ ::WillPaginate::Collection.create( options[:page], options[:per_page] ) do |pager|
121
+ # perform view count first (should create designs if missing)
122
+ if view_name.to_sym == :all
123
+ pager.total_entries = count({:database => options[:database]})
124
+ else
125
+ total = view( view_name, options.update(:reduce => true).dup )['rows'].pop
126
+ pager.total_entries = total ? total['value'] : 0
139
127
  end
128
+ p_options = options.merge(
129
+ :design_doc => self.to_s,
130
+ :view_name => view_name,
131
+ :include_docs => true
132
+ )
133
+ # Only provide the reduce parameter when necessary. This is when the view has
134
+ # been set with a reduce method and requires the reduce boolean parameter
135
+ # to be either true or false on all requests.
136
+ p_options[:reduce] = false unless view_name.to_sym == :all
137
+ results = paginate(p_options)
138
+ pager.replace( results )
140
139
  end
141
140
  end
142
-
143
141
  end
144
- end # module mixins
142
+
143
+ end
145
144
  end # module CouchRest
146
145
 
147
146
 
@@ -1,28 +1,26 @@
1
1
  module CouchRest
2
- module Mixins
3
- module WillPaginate
4
- module ProxyMethods
2
+ module WillPaginate
3
+ module ProxyMethods
5
4
 
6
- def method_missing(m, *args, &block)
7
- if m.to_s =~ /^paginate_(.+)/ && @klass.respond_to?(m)
8
- view_name = $1 # view name
9
- opts = args.shift || {}
10
- paginated_view(view_name, opts)
11
- else
12
- super
13
- end
14
- end
15
-
16
- def paginated_view(view_name, opts = {})
17
- opts = {
18
- :database => @database
19
- }.merge(opts)
20
- result = @klass.paginated_view(view_name, opts)
21
- result.each{|doc| doc.database = @database if respond_to?(:database) } if result
22
- result
5
+ def method_missing(m, *args, &block)
6
+ if m.to_s =~ /^paginate_(.+)/ && @klass.respond_to?(m)
7
+ view_name = $1 # view name
8
+ opts = args.shift || {}
9
+ paginated_view(view_name, opts)
10
+ else
11
+ super
23
12
  end
13
+ end
24
14
 
15
+ def paginated_view(view_name, opts = {})
16
+ opts = {
17
+ :database => @database
18
+ }.merge(opts)
19
+ result = @klass.paginated_view(view_name, opts)
20
+ result.each{|doc| doc.database = @database if respond_to?(:database) } if result
21
+ result
25
22
  end
23
+
26
24
  end
27
25
  end
28
26
  end
data/spec/spec_helper.rb CHANGED
@@ -2,12 +2,13 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
 
4
4
  require 'rubygems'
5
- require 'couchrest'
6
- require 'will_paginate'
5
+ require 'couchrest_extended_document'
6
+ require 'couchrest_model'
7
7
  require 'will_paginate_couchrest'
8
8
  require 'spec'
9
9
  require 'spec/autorun'
10
10
 
11
+
11
12
  unless defined?(SPEC_COUCH)
12
13
  COUCH_URL = "http://127.0.0.1:5984"
13
14
  COUCH_NAME = 'couchrest-test'
@@ -26,6 +27,6 @@ Spec::Runner.configure do |config|
26
27
  }
27
28
 
28
29
  config.after(:all) do
29
- SPEC_COUCH.delete! rescue nil
30
+ SPEC_COUCH.delete!
30
31
  end
31
32
  end
@@ -1,97 +1,104 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe CouchRest::Mixins::WillPaginate do
3
+ describe CouchRest::WillPaginate do
4
4
 
5
- class SomeDoc < CouchRest::ExtendedDocument
5
+ class SomeExtendedDoc < CouchRest::ExtendedDocument
6
6
  use_database SPEC_COUCH
7
-
8
7
  property :name
9
-
10
8
  paginated_view_by :name
11
9
  end
12
10
 
13
- it "should respond to paginated_view_by class method" do
14
- SomeDoc.should respond_to :paginated_view_by
15
- end
16
-
17
- it "should call view_by method when paginated view_by included" do
18
- SomeDoc.should_receive(:view_by)
19
- class SomeDoc
20
- paginated_view_by :name
21
- end
22
- end
23
-
24
- it "should respond to the view and paginated method" do
25
- SomeDoc.should respond_to :paginate_by_name
26
- # @some_doc.stub(:id).and_return(123)
27
- end
28
-
29
- it "should accept request when no results" do
30
- docs = SomeDoc.paginate_by_name(:per_page => 5)
31
- docs.total_entries.should eql(0)
11
+ class SomeModel < CouchRest::Model::Base
12
+ use_database SPEC_COUCH
13
+ property :name
14
+ paginated_view_by :name
32
15
  end
33
16
 
34
- it "should accept request without page" do
35
- docs = nil
36
- lambda { docs = SomeDoc.paginate_by_name(:per_page => 5) }.should_not raise_error
37
- docs.current_page.should eql(1)
38
- end
17
+ [SomeExtendedDoc, SomeModel].each do |klass|
18
+
19
+ describe klass do
39
20
 
40
- it "should throw an exception when missing per_page parameter" do
41
- lambda { SomeDoc.paginate_by_name() }.should raise_error
42
- end
21
+ before(:all) do
22
+ reset_test_db!
23
+ end
43
24
 
25
+ it "should respond to paginated_view_by class method" do
26
+ klass.should respond_to :paginated_view_by
27
+ end
44
28
 
45
- describe "performing pagination with lots of documents" do
29
+ it "should call view_by method when paginated view_by included" do
30
+ klass.should_receive(:view_by)
31
+ klass.paginated_view_by :name
32
+ end
33
+
34
+ it "should respond to the view and paginated method" do
35
+ klass.should respond_to :paginate_by_name
36
+ # @some_doc.stub(:id).and_return(123)
37
+ end
46
38
 
47
- before(:each) do
48
- reset_test_db!
49
- 20.times do |i|
50
- txt = "%02d" % i
51
- SomeDoc.new(:name => "document #{txt}").save
39
+ it "should accept request when no results" do
40
+ docs = klass.paginate_by_name(:per_page => 5)
41
+ docs.total_entries.should eql(0)
52
42
  end
53
- end
54
43
 
55
- it "should produce a will paginate collection" do
56
- docs = SomeDoc.paginate_by_name( :page => 1, :per_page => 5 )
57
- docs.should be_a_kind_of(::WillPaginate::Collection)
58
- docs.total_pages.should eql(4)
59
- docs.first.name.should eql('document 00')
60
- docs.length.should eql(5)
61
- docs.last.name.should eql('document 04')
62
- end
44
+ it "should accept request without page" do
45
+ docs = nil
46
+ lambda { docs = klass.paginate_by_name(:per_page => 5) }.should_not raise_error
47
+ docs.current_page.should eql(1)
48
+ end
63
49
 
64
- it "should produce second page from paginate collection" do
65
- docs = SomeDoc.paginate_by_name( :page => 2, :per_page => 5 )
66
- docs.first.name.should eql('document 05')
67
- docs.length.should eql(5)
68
- docs.last.name.should eql('document 09')
69
- end
50
+ it "should throw an exception when missing per_page parameter" do
51
+ lambda { klass.paginate_by_name() }.should raise_error
52
+ end
70
53
 
71
- it "should perform paginate on all entries" do
72
- docs = SomeDoc.paginate_all(:page => 1, :per_page => 5)
73
- docs.first.class.should eql(SomeDoc)
74
- docs.total_pages.should eql(4)
75
- docs.total_entries.should eql(20)
76
- docs.length.should eql(5)
77
- end
78
54
 
79
- end
55
+ describe "performing pagination with lots of documents" do
56
+
57
+ before(:each) do
58
+ reset_test_db!
59
+ 20.times do |i|
60
+ txt = "%02d" % i
61
+ klass.new(:name => "document #{txt}").save
62
+ end
63
+ end
64
+
65
+ it "should produce a will paginate collection" do
66
+ docs = klass.paginate_by_name( :page => 1, :per_page => 5 )
67
+ docs.should be_a_kind_of(::WillPaginate::Collection)
68
+ docs.total_pages.should eql(4)
69
+ docs.first.name.should eql('document 00')
70
+ docs.length.should eql(5)
71
+ docs.last.name.should eql('document 04')
72
+ end
73
+
74
+ it "should produce second page from paginate collection" do
75
+ docs = klass.paginate_by_name( :page => 2, :per_page => 5 )
76
+ docs.first.name.should eql('document 05')
77
+ docs.length.should eql(5)
78
+ docs.last.name.should eql('document 09')
79
+ end
80
+
81
+ it "should perform paginate on all entries" do
82
+ docs = klass.paginate_all(:page => 1, :per_page => 5)
83
+ docs.first.class.should eql(klass)
84
+ docs.total_pages.should eql(4)
85
+ docs.total_entries.should eql(20)
86
+ docs.length.should eql(5)
87
+ end
80
88
 
89
+ end
81
90
 
82
- describe "using pagination via proxy class" do
83
- before(:each) do
84
- @proxy = SomeDoc.on(SPEC_COUCH)
85
- end
86
91
 
87
- it "should allow paginate call on proxy with database" do
88
- SomeDoc.should_receive(:paginated_view).with('by_name', {:key => 'foo', :database => SPEC_COUCH})
89
- @proxy.paginate_by_name :key => 'foo'
90
- end
92
+ describe "using pagination via proxy class" do
93
+ before(:each) do
94
+ @proxy = klass.on(SPEC_COUCH)
95
+ end
91
96
 
92
- it "should call paginate parent with database" do
93
- SomeDoc.should_receive(:paginate).with(hash_including(:database => SPEC_COUCH)).and_return([])
94
- @proxy.paginate_by_name :key => 'foo', :per_page => 10
97
+ it "should allow paginate call on proxy" do
98
+ klass.should_receive(:paginated_view).with('by_name', {:key => 'foo', :database => SPEC_COUCH})
99
+ @proxy.paginate_by_name :key => 'foo'
100
+ end
101
+ end
95
102
  end
96
103
  end
97
104
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- - 2
9
- version: 0.2.2
7
+ - 3
8
+ - 1
9
+ version: 0.3.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - samlown
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-05 00:00:00 +00:00
17
+ date: 2010-07-07 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -96,5 +96,5 @@ signing_key:
96
96
  specification_version: 3
97
97
  summary: adds will-paginate support to CouchRest
98
98
  test_files:
99
- - spec/will_paginate_couchrest_spec.rb
100
99
  - spec/spec_helper.rb
100
+ - spec/will_paginate_couchrest_spec.rb