will_paginate_couchrest 0.1.1 → 0.2.0
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 +6 -0
- data/VERSION +1 -1
- data/lib/will_paginate_couchrest/class_methods.rb +149 -0
- data/lib/will_paginate_couchrest/proxy_methods.rb +17 -0
- data/lib/will_paginate_couchrest.rb +12 -150
- data/spec/will_paginate_couchrest_spec.rb +12 -0
- metadata +7 -5
data/README.rdoc
CHANGED
@@ -8,6 +8,12 @@ http://www.opensourcery.co.za/2010/02/08/paginating-documents-with-couchrest-and
|
|
8
8
|
|
9
9
|
Automatically generate views with an extra reduce method used to generate the total number of documents.
|
10
10
|
|
11
|
+
== History
|
12
|
+
|
13
|
+
2010-04-05 - 0.2.0 - Added support for CouchRest Proxy class
|
14
|
+
|
15
|
+
2010-03-05 - 0.1.0 - Initial version
|
16
|
+
|
11
17
|
== Install
|
12
18
|
|
13
19
|
gem install will_paginate_couchrest
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module CouchRest
|
2
|
+
module Mixins
|
3
|
+
module WillPaginate
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
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)
|
65
|
+
|
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}"
|
70
|
+
|
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
|
76
|
+
|
77
|
+
opts = {
|
78
|
+
:map => "
|
79
|
+
function( doc ) {
|
80
|
+
if (#{guards.join(' && ')}) {
|
81
|
+
emit(#{key_emit}, 1 );
|
82
|
+
}
|
83
|
+
}
|
84
|
+
",
|
85
|
+
:reduce => "
|
86
|
+
function(keys, values, rereduce) {
|
87
|
+
return sum(values);
|
88
|
+
}
|
89
|
+
"
|
90
|
+
}.merge(opts)
|
91
|
+
|
92
|
+
# View prepared, send to traditional view_by
|
93
|
+
view_by keys, opts
|
94
|
+
|
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
|
101
|
+
|
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
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
##
|
116
|
+
# Return a WillPaginate collection suitable for usage
|
117
|
+
#
|
118
|
+
def paginated_view(view_name, options = {})
|
119
|
+
raise "Missing per_page parameter" if options[:per_page].nil?
|
120
|
+
|
121
|
+
options[:page] ||= 1
|
122
|
+
|
123
|
+
::WillPaginate::Collection.create( options[:page], options[:per_page] ) do |pager|
|
124
|
+
# perform view count first (should create designs if missing)
|
125
|
+
if view_name.to_sym == :all
|
126
|
+
pager.total_entries = count()
|
127
|
+
else
|
128
|
+
total = view( view_name, options.update(:reduce => true) )['rows'].pop
|
129
|
+
pager.total_entries = total ? total['value'] : 0
|
130
|
+
end
|
131
|
+
p_options = options.merge(
|
132
|
+
:design_doc => self.to_s, :view_name => view_name,
|
133
|
+
:include_docs => true
|
134
|
+
)
|
135
|
+
# Only provide the reduce parameter when necessary. This is when the view has
|
136
|
+
# been set with a reduce method and requires the reduce boolean parameter
|
137
|
+
# to be either true or false on all requests.
|
138
|
+
p_options[:reduce] = false unless view_name.to_sym == :all
|
139
|
+
results = paginate(p_options)
|
140
|
+
pager.replace( results )
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end # module mixins
|
147
|
+
end # module CouchRest
|
148
|
+
|
149
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module CouchRest
|
2
|
+
module Mixins
|
3
|
+
module WillPaginate
|
4
|
+
module ProxyMethods
|
5
|
+
|
6
|
+
def method_missing(m, *args, &block)
|
7
|
+
if m.to_s =~ /^paginate_(.+)/ && @klass.respond_to?(m)
|
8
|
+
@klass.send(m, *args)
|
9
|
+
else
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,154 +1,6 @@
|
|
1
|
-
# Based on original validators in CouchRest::Validation
|
2
|
-
require 'couchrest/mixins/validation'
|
3
|
-
|
4
|
-
module CouchRest
|
5
|
-
module Mixins
|
6
|
-
module WillPaginate
|
7
|
-
|
8
|
-
def self.included(base)
|
9
|
-
base.extend(ClassMethods)
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
# Define a CouchDB will paginate view. The name of the view will be the concatenation
|
14
|
-
# of <tt>paginate_by</tt> and the keys joined by <tt>_and_</tt>
|
15
|
-
#
|
16
|
-
# ==== Example paginated views:
|
17
|
-
#
|
18
|
-
# class Post
|
19
|
-
# # view with default options
|
20
|
-
# # query with Post.paginate_by_date
|
21
|
-
# paginated_view_by :date, :descending => true
|
22
|
-
#
|
23
|
-
# # view with compound sort-keys
|
24
|
-
# # query with Post.by_user_id_and_date
|
25
|
-
# paginated_view_by :user_id, :date
|
26
|
-
#
|
27
|
-
# # view with custom map/reduce functions
|
28
|
-
# # query with Post.by_tags :reduce => true
|
29
|
-
# paginated_view_by :tags,
|
30
|
-
# :map =>
|
31
|
-
# "function(doc) {
|
32
|
-
# if (doc['couchrest-type'] == 'Post' && doc.tags) {
|
33
|
-
# doc.tags.forEach(function(tag){
|
34
|
-
# emit(doc.tag, 1);
|
35
|
-
# });
|
36
|
-
# }
|
37
|
-
# }",
|
38
|
-
# :reduce =>
|
39
|
-
# "function(keys, values, rereduce) {
|
40
|
-
# return sum(values);
|
41
|
-
# }"
|
42
|
-
# end
|
43
|
-
#
|
44
|
-
# <tt>paginated_view_by :date</tt> will create a view defined by this Javascript
|
45
|
-
# function:
|
46
|
-
#
|
47
|
-
# function(doc) {
|
48
|
-
# if (doc['couchrest-type'] == 'Post' && doc.date) {
|
49
|
-
# emit(doc.date, 1);
|
50
|
-
# }
|
51
|
-
# }
|
52
|
-
#
|
53
|
-
# And a standard summing reduce function like the following:
|
54
|
-
#
|
55
|
-
# function(keys, values, rereduce) {
|
56
|
-
# return sum(values);
|
57
|
-
# }
|
58
|
-
#
|
59
|
-
# It can be queried by calling <tt>Post.paginate_by_date</tt> which accepts all
|
60
|
-
# valid options for CouchRest::Database#view. In addition, calling with
|
61
|
-
# the <tt>:raw => true</tt> option will return the view rows
|
62
|
-
# themselves. By default <tt>Post.by_date</tt> will return the
|
63
|
-
# documents included in the generated view.
|
64
|
-
#
|
65
|
-
# For further details on <tt>view_by</tt>'s other options, please see the
|
66
|
-
# standard documentation.
|
67
|
-
def paginated_view_by(*keys)
|
68
|
-
|
69
|
-
# Prepare the Traditional view
|
70
|
-
opts = keys.last.is_a?(Hash) ? keys.pop : {}
|
71
|
-
view_name = "by_#{keys.join('_and_')}"
|
72
|
-
method_name = "paginate_#{view_name}"
|
73
|
-
|
74
|
-
doc_keys = keys.collect{|k| "doc['#{k}']"}
|
75
|
-
key_emit = doc_keys.length == 1 ? "#{doc_keys.first}" : "[#{doc_keys.join(', ')}]"
|
76
|
-
guards = opts.delete(:guards) || []
|
77
|
-
guards.push("(doc['couchrest-type'] == '#{self.to_s}')")
|
78
|
-
guards.concat doc_keys
|
79
|
-
|
80
|
-
opts.reverse_merge!(
|
81
|
-
:map => "
|
82
|
-
function( doc ) {
|
83
|
-
if (#{guards.join(' && ')}) {
|
84
|
-
emit(#{key_emit}, 1 );
|
85
|
-
}
|
86
|
-
}
|
87
|
-
",
|
88
|
-
:reduce => "
|
89
|
-
function(keys, values, rereduce) {
|
90
|
-
return sum(values);
|
91
|
-
}
|
92
|
-
"
|
93
|
-
)
|
94
|
-
|
95
|
-
# View prepared, send to traditional view_by
|
96
|
-
view_by keys, opts
|
97
|
-
|
98
|
-
instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
99
|
-
def #{method_name}(options = {})
|
100
|
-
paginated_view('#{view_name}', options)
|
101
|
-
end
|
102
|
-
RUBY_EVAL
|
103
|
-
end
|
104
|
-
|
105
|
-
##
|
106
|
-
# Generate a Will Paginate collection from all the available
|
107
|
-
# documents stored with a matching couchrest-type.
|
108
|
-
#
|
109
|
-
# Requires no declaration as the 'all' view is built into couchrest
|
110
|
-
# Extended Documents.
|
111
|
-
#
|
112
|
-
def paginate_all(options = {})
|
113
|
-
paginated_view(:all, options)
|
114
|
-
end
|
115
|
-
|
116
|
-
protected
|
117
|
-
|
118
|
-
##
|
119
|
-
# Return a WillPaginate collection suitable for usage
|
120
|
-
#
|
121
|
-
def paginated_view(view_name, options = {})
|
122
|
-
raise "Missing per_page parameter" if options[:per_page].nil?
|
123
|
-
|
124
|
-
options[:page] ||= 1
|
125
|
-
|
126
|
-
::WillPaginate::Collection.create( options[:page], options[:per_page] ) do |pager|
|
127
|
-
# perform view count first (should create designs if missing)
|
128
|
-
if view_name.to_sym == :all
|
129
|
-
pager.total_entries = count()
|
130
|
-
else
|
131
|
-
total = view( view_name, options.update(:reduce => true) )['rows'].pop
|
132
|
-
pager.total_entries = total ? total['value'] : 0
|
133
|
-
end
|
134
|
-
p_options = options.merge(
|
135
|
-
:design_doc => self.to_s, :view_name => view_name,
|
136
|
-
:include_docs => true
|
137
|
-
)
|
138
|
-
# Only provide the reduce parameter when necessary. This is when the view has
|
139
|
-
# been set with a reduce method and requires the reduce boolean parameter
|
140
|
-
# to be either true or false on all requests.
|
141
|
-
p_options[:reduce] = false unless view_name.to_sym == :all
|
142
|
-
results = paginate(p_options)
|
143
|
-
pager.replace( results )
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
149
|
-
end # module mixins
|
150
|
-
end # module CouchRest
|
151
1
|
|
2
|
+
require('will_paginate_couchrest/class_methods')
|
3
|
+
require('will_paginate_couchrest/proxy_methods')
|
152
4
|
|
153
5
|
# Take the liberty of adding ourself to the couchrest library
|
154
6
|
|
@@ -158,3 +10,13 @@ module CouchRest
|
|
158
10
|
end
|
159
11
|
end
|
160
12
|
|
13
|
+
module CouchRest
|
14
|
+
module Mixins
|
15
|
+
module ClassProxy
|
16
|
+
class Proxy
|
17
|
+
include CouchRest::Mixins::WillPaginate::ProxyMethods
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -77,5 +77,17 @@ describe CouchRest::Mixins::WillPaginate do
|
|
77
77
|
end
|
78
78
|
|
79
79
|
end
|
80
|
+
|
81
|
+
|
82
|
+
describe "using pagination via proxy class" do
|
83
|
+
before(:all) do
|
84
|
+
@proxy = SomeDoc.on(SPEC_COUCH)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should allow paginate call on proxy" do
|
88
|
+
SomeDoc.should_receive(:paginate_by_name)
|
89
|
+
@proxy.paginate_by_name :key => 'foo'
|
90
|
+
end
|
91
|
+
end
|
80
92
|
end
|
81
93
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
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-
|
17
|
+
date: 2010-04-05 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -60,6 +60,8 @@ files:
|
|
60
60
|
- Rakefile
|
61
61
|
- VERSION
|
62
62
|
- lib/will_paginate_couchrest.rb
|
63
|
+
- lib/will_paginate_couchrest/class_methods.rb
|
64
|
+
- lib/will_paginate_couchrest/proxy_methods.rb
|
63
65
|
- spec/spec.opts
|
64
66
|
- spec/spec_helper.rb
|
65
67
|
- spec/will_paginate_couchrest_spec.rb
|
@@ -94,5 +96,5 @@ signing_key:
|
|
94
96
|
specification_version: 3
|
95
97
|
summary: adds will-paginate support to CouchRest
|
96
98
|
test_files:
|
97
|
-
- spec/spec_helper.rb
|
98
99
|
- spec/will_paginate_couchrest_spec.rb
|
100
|
+
- spec/spec_helper.rb
|