will_paginate_couchrest 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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