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 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.1
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
- - 1
8
- - 1
9
- version: 0.1.1
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-03-05 00:00:00 +01:00
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