couchrest_model 1.0.0 → 1.1.0.beta
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/.gitignore +1 -1
- data/Gemfile.lock +19 -20
- data/README.md +145 -20
- data/VERSION +1 -1
- data/couchrest_model.gemspec +2 -3
- data/history.txt +14 -0
- data/lib/couchrest/model/associations.rb +4 -4
- data/lib/couchrest/model/base.rb +5 -0
- data/lib/couchrest/model/callbacks.rb +1 -2
- data/lib/couchrest/model/collection.rb +1 -1
- data/lib/couchrest/model/designs/view.rb +486 -0
- data/lib/couchrest/model/designs.rb +81 -0
- data/lib/couchrest/model/document_queries.rb +1 -1
- data/lib/couchrest/model/persistence.rb +25 -16
- data/lib/couchrest/model/properties.rb +5 -1
- data/lib/couchrest/model/property.rb +2 -2
- data/lib/couchrest/model/proxyable.rb +152 -0
- data/lib/couchrest/model/typecast.rb +1 -1
- data/lib/couchrest/model/validations/casted_model.rb +3 -1
- data/lib/couchrest/model/validations/locale/en.yml +1 -1
- data/lib/couchrest/model/validations/uniqueness.rb +6 -7
- data/lib/couchrest/model/validations.rb +1 -0
- data/lib/couchrest/model/views.rb +11 -9
- data/lib/couchrest_model.rb +3 -0
- data/spec/couchrest/assocations_spec.rb +2 -2
- data/spec/couchrest/base_spec.rb +15 -1
- data/spec/couchrest/casted_model_spec.rb +30 -12
- data/spec/couchrest/class_proxy_spec.rb +2 -2
- data/spec/couchrest/collection_spec.rb +89 -0
- data/spec/couchrest/designs/view_spec.rb +766 -0
- data/spec/couchrest/designs_spec.rb +110 -0
- data/spec/couchrest/persistence_spec.rb +36 -7
- data/spec/couchrest/property_spec.rb +15 -0
- data/spec/couchrest/proxyable_spec.rb +329 -0
- data/spec/couchrest/{validations.rb → validations_spec.rb} +1 -3
- data/spec/couchrest/view_spec.rb +19 -91
- data/spec/fixtures/base.rb +8 -6
- data/spec/fixtures/more/article.rb +1 -1
- data/spec/fixtures/more/course.rb +4 -2
- metadata +21 -76
- data/lib/couchrest/model/view.rb +0 -190
@@ -58,8 +58,8 @@ module CouchRest::Model
|
|
58
58
|
if default.class == Proc
|
59
59
|
default.call
|
60
60
|
else
|
61
|
-
#
|
62
|
-
default
|
61
|
+
# TODO identify cause of mutex errors
|
62
|
+
Marshal.load(Marshal.dump(default))
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module CouchRest
|
2
|
+
module Model
|
3
|
+
# :nodoc: Because I like inventing words
|
4
|
+
module Proxyable
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
attr_accessor :model_proxy
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
# Define a collection that will use the base model for the database connection
|
14
|
+
# details.
|
15
|
+
def proxy_for(model_name, options = {})
|
16
|
+
db_method = options[:database_method] || "proxy_database"
|
17
|
+
options[:class_name] ||= model_name.to_s.singularize.camelize
|
18
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
19
|
+
def #{model_name}
|
20
|
+
unless respond_to?('#{db_method}')
|
21
|
+
raise "Missing ##{db_method} method for proxy"
|
22
|
+
end
|
23
|
+
@#{model_name} ||= CouchRest::Model::Proxyable::ModelProxy.new(::#{options[:class_name]}, self, self.class.to_s.underscore, #{db_method})
|
24
|
+
end
|
25
|
+
EOS
|
26
|
+
end
|
27
|
+
|
28
|
+
def proxied_by(model_name, options = {})
|
29
|
+
raise "Model can only be proxied once or ##{model_name} already defined" if method_defined?(model_name)
|
30
|
+
attr_accessor model_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class ModelProxy
|
35
|
+
|
36
|
+
attr_reader :model, :owner, :owner_name, :database
|
37
|
+
|
38
|
+
def initialize(model, owner, owner_name, database)
|
39
|
+
@model = model
|
40
|
+
@owner = owner
|
41
|
+
@owner_name = owner_name
|
42
|
+
@database = database
|
43
|
+
end
|
44
|
+
|
45
|
+
# Base
|
46
|
+
|
47
|
+
def new(*args)
|
48
|
+
proxy_update(model.new(*args))
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_from_database(doc = {})
|
52
|
+
proxy_update(model.build_from_database(doc))
|
53
|
+
end
|
54
|
+
|
55
|
+
def method_missing(m, *args, &block)
|
56
|
+
if has_view?(m)
|
57
|
+
if model.respond_to?(m)
|
58
|
+
return model.send(m, *args).proxy(self)
|
59
|
+
else
|
60
|
+
query = args.shift || {}
|
61
|
+
return view(m, query, *args, &block)
|
62
|
+
end
|
63
|
+
elsif m.to_s =~ /^find_(by_.+)/
|
64
|
+
view_name = $1
|
65
|
+
if has_view?(view_name)
|
66
|
+
return first_from_view(view_name, *args)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
# DocumentQueries
|
73
|
+
|
74
|
+
def all(opts = {}, &block)
|
75
|
+
proxy_update_all(@model.all({:database => @database}.merge(opts), &block))
|
76
|
+
end
|
77
|
+
|
78
|
+
def count(opts = {})
|
79
|
+
@model.count({:database => @database}.merge(opts))
|
80
|
+
end
|
81
|
+
|
82
|
+
def first(opts = {})
|
83
|
+
proxy_update(@model.first({:database => @database}.merge(opts)))
|
84
|
+
end
|
85
|
+
|
86
|
+
def last(opts = {})
|
87
|
+
proxy_update(@model.last({:database => @database}.merge(opts)))
|
88
|
+
end
|
89
|
+
|
90
|
+
def get(id)
|
91
|
+
proxy_update(@model.get(id, @database))
|
92
|
+
end
|
93
|
+
alias :find :get
|
94
|
+
|
95
|
+
# Views
|
96
|
+
|
97
|
+
def has_view?(view)
|
98
|
+
@model.has_view?(view)
|
99
|
+
end
|
100
|
+
|
101
|
+
def view_by(*args)
|
102
|
+
@model.view_by(*args)
|
103
|
+
end
|
104
|
+
|
105
|
+
def view(name, query={}, &block)
|
106
|
+
proxy_update_all(@model.view(name, {:database => @database}.merge(query), &block))
|
107
|
+
end
|
108
|
+
|
109
|
+
def first_from_view(name, *args)
|
110
|
+
# add to first hash available, or add to end
|
111
|
+
(args.last.is_a?(Hash) ? args.last : (args << {}).last)[:database] = @database
|
112
|
+
proxy_update(@model.first_from_view(name, *args))
|
113
|
+
end
|
114
|
+
|
115
|
+
# DesignDoc
|
116
|
+
|
117
|
+
def design_doc
|
118
|
+
@model.design_doc
|
119
|
+
end
|
120
|
+
|
121
|
+
def refresh_design_doc(db = nil)
|
122
|
+
@model.refresh_design_doc(db || @database)
|
123
|
+
end
|
124
|
+
|
125
|
+
def save_design_doc(db = nil)
|
126
|
+
@model.save_design_doc(db || @database)
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
protected
|
131
|
+
|
132
|
+
# Update the document's proxy details, specifically, the fields that
|
133
|
+
# link back to the original document.
|
134
|
+
def proxy_update(doc)
|
135
|
+
if doc
|
136
|
+
doc.database = @database if doc.respond_to?(:database=)
|
137
|
+
doc.model_proxy = self if doc.respond_to?(:model_proxy=)
|
138
|
+
doc.send("#{owner_name}=", owner) if doc.respond_to?("#{owner_name}=")
|
139
|
+
end
|
140
|
+
doc
|
141
|
+
end
|
142
|
+
|
143
|
+
def proxy_update_all(docs)
|
144
|
+
docs.each do |doc|
|
145
|
+
proxy_update(doc)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -79,7 +79,7 @@ module CouchRest
|
|
79
79
|
# Match numeric string
|
80
80
|
def typecast_to_numeric(value, method)
|
81
81
|
if value.respond_to?(:to_str)
|
82
|
-
if value.gsub(/,/, '.').gsub(/\.(?!\d*\Z)/, '').to_str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
|
82
|
+
if value.strip.gsub(/,/, '.').gsub(/\.(?!\d*\Z)/, '').to_str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
|
83
83
|
$1.send(method)
|
84
84
|
else
|
85
85
|
value
|
@@ -6,7 +6,9 @@ module CouchRest
|
|
6
6
|
def validate_each(document, attribute, value)
|
7
7
|
values = value.is_a?(Array) ? value : [value]
|
8
8
|
return if values.collect {|doc| doc.nil? || doc.valid? }.all?
|
9
|
-
|
9
|
+
error_options = { :value => value }
|
10
|
+
error_options[:message] = options[:message] if options[:message]
|
11
|
+
document.errors.add(attribute, :invalid, error_options)
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -9,19 +9,19 @@ module CouchRest
|
|
9
9
|
|
10
10
|
# Ensure we have a class available so we can check for a usable view
|
11
11
|
# or add one if necessary.
|
12
|
-
def setup(
|
13
|
-
@
|
12
|
+
def setup(model)
|
13
|
+
@model = model
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
16
|
def validate_each(document, attribute, value)
|
18
17
|
view_name = options[:view].nil? ? "by_#{attribute}" : options[:view]
|
18
|
+
model = document.model_proxy || @model
|
19
19
|
# Determine the base of the search
|
20
|
-
base = options[:proxy].nil? ?
|
20
|
+
base = options[:proxy].nil? ? model : document.instance_eval(options[:proxy])
|
21
21
|
|
22
22
|
if base.respond_to?(:has_view?) && !base.has_view?(view_name)
|
23
23
|
raise "View #{document.class.name}.#{options[:view]} does not exist!" unless options[:view].nil?
|
24
|
-
|
24
|
+
model.view_by attribute
|
25
25
|
end
|
26
26
|
|
27
27
|
docs = base.view(view_name, :key => value, :limit => 2, :include_docs => false)['rows']
|
@@ -32,11 +32,10 @@ module CouchRest
|
|
32
32
|
end
|
33
33
|
|
34
34
|
if docs.length > 0
|
35
|
-
document.errors.add(attribute, :taken,
|
35
|
+
document.errors.add(attribute, :taken, options.merge(:value => value))
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
39
|
end
|
41
40
|
|
42
41
|
end
|
@@ -85,9 +85,14 @@ module CouchRest
|
|
85
85
|
end
|
86
86
|
|
87
87
|
# returns stored defaults if there is a view named this in the design doc
|
88
|
-
def has_view?(
|
89
|
-
|
90
|
-
|
88
|
+
def has_view?(name)
|
89
|
+
design_doc && design_doc.has_view?(name)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Check if the view can be reduced by checking to see if it has a
|
93
|
+
# reduce function.
|
94
|
+
def can_reduce_view?(name)
|
95
|
+
design_doc && design_doc.can_reduce_view?(name)
|
91
96
|
end
|
92
97
|
|
93
98
|
# Dispatches to any named view.
|
@@ -127,12 +132,9 @@ module CouchRest
|
|
127
132
|
if raw || (opts.has_key?(:include_docs) && opts[:include_docs] == false)
|
128
133
|
fetch_view(db, name, opts, &block)
|
129
134
|
else
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
view = fetch_view db, name, opts.merge({:include_docs => true}), &block
|
134
|
-
view['rows'].collect{|r|create_from_database(r['doc'])} if view['rows']
|
135
|
-
end
|
135
|
+
opts = opts.merge(:include_docs => true)
|
136
|
+
view = fetch_view db, name, opts, &block
|
137
|
+
view['rows'].collect{|r| build_from_database(r['doc'])} if view['rows']
|
136
138
|
end
|
137
139
|
end
|
138
140
|
|
data/lib/couchrest_model.rb
CHANGED
@@ -37,9 +37,12 @@ require "couchrest/model/views"
|
|
37
37
|
require "couchrest/model/design_doc"
|
38
38
|
require "couchrest/model/extended_attachments"
|
39
39
|
require "couchrest/model/class_proxy"
|
40
|
+
require "couchrest/model/proxyable"
|
40
41
|
require "couchrest/model/collection"
|
41
42
|
require "couchrest/model/associations"
|
42
43
|
require "couchrest/model/configuration"
|
44
|
+
require "couchrest/model/designs"
|
45
|
+
require "couchrest/model/designs/view"
|
43
46
|
|
44
47
|
# Monkey patches applied to couchrest
|
45
48
|
require "couchrest/model/support/couchrest"
|
@@ -44,11 +44,11 @@ describe "Assocations" do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should raise error if class name does not exist" do
|
47
|
-
lambda
|
47
|
+
lambda do
|
48
48
|
class TestBadAssoc < CouchRest::Model::Base
|
49
49
|
belongs_to :test_bad_item
|
50
50
|
end
|
51
|
-
|
51
|
+
end.should raise_error(NameError, /TestBadAssoc#test_bad_item/)
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should allow override of foreign key" do
|
data/spec/couchrest/base_spec.rb
CHANGED
@@ -34,10 +34,16 @@ describe "Model Base" do
|
|
34
34
|
@obj.should be_new_record
|
35
35
|
end
|
36
36
|
|
37
|
-
it "should not
|
37
|
+
it "should not fail with nil argument" do
|
38
38
|
@obj = Basic.new(nil)
|
39
39
|
@obj.should_not be_nil
|
40
40
|
end
|
41
|
+
|
42
|
+
it "should allow the database to be set" do
|
43
|
+
@obj = Basic.new(nil, :database => 'database')
|
44
|
+
@obj.database.should eql('database')
|
45
|
+
end
|
46
|
+
|
41
47
|
end
|
42
48
|
|
43
49
|
describe "ActiveModel compatability Basic" do
|
@@ -184,6 +190,14 @@ describe "Model Base" do
|
|
184
190
|
obj = WithDefaultValues.new(:preset => 'test')
|
185
191
|
obj.preset = 'test'
|
186
192
|
end
|
193
|
+
|
194
|
+
it "should keep default values for new instances" do
|
195
|
+
obj = WithDefaultValues.new
|
196
|
+
obj.preset[:alpha] = 123
|
197
|
+
obj.preset.should == {:right => 10, :top_align => false, :alpha => 123}
|
198
|
+
another = WithDefaultValues.new
|
199
|
+
another.preset.should == {:right => 10, :top_align => false}
|
200
|
+
end
|
187
201
|
|
188
202
|
it "should work with a default empty array" do
|
189
203
|
obj = WithDefaultValues.new(:tags => ['spec'])
|
@@ -24,19 +24,24 @@ class DummyModel < CouchRest::Model::Base
|
|
24
24
|
property :sub_models do |child|
|
25
25
|
child.property :title
|
26
26
|
end
|
27
|
+
property :param_free_sub_models do
|
28
|
+
property :title
|
29
|
+
end
|
27
30
|
end
|
28
31
|
|
29
32
|
class WithCastedCallBackModel < Hash
|
30
33
|
include CouchRest::Model::CastedModel
|
31
34
|
property :name
|
32
|
-
property :
|
33
|
-
property :
|
35
|
+
property :run_before_validation
|
36
|
+
property :run_after_validation
|
37
|
+
|
38
|
+
validates_presence_of :run_before_validation
|
34
39
|
|
35
|
-
|
36
|
-
object.
|
40
|
+
before_validation do |object|
|
41
|
+
object.run_before_validation = true
|
37
42
|
end
|
38
|
-
|
39
|
-
object.
|
43
|
+
after_validation do |object|
|
44
|
+
object.run_after_validation = true
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
@@ -98,6 +103,14 @@ describe CouchRest::Model::CastedModel do
|
|
98
103
|
@obj.sub_models << {:title => 'test'}
|
99
104
|
@obj.sub_models.first.title.should eql('test')
|
100
105
|
end
|
106
|
+
it "should be empty intitally (without params)" do
|
107
|
+
@obj.param_free_sub_models.should_not be_nil
|
108
|
+
@obj.param_free_sub_models.should be_empty
|
109
|
+
end
|
110
|
+
it "should be updatable using a hash (without params)" do
|
111
|
+
@obj.param_free_sub_models << {:title => 'test'}
|
112
|
+
@obj.param_free_sub_models.first.title.should eql('test')
|
113
|
+
end
|
101
114
|
end
|
102
115
|
|
103
116
|
describe "casted as attribute" do
|
@@ -284,6 +297,11 @@ describe CouchRest::Model::CastedModel do
|
|
284
297
|
@toy2.errors.should be_empty
|
285
298
|
@toy3.errors.should_not be_empty
|
286
299
|
end
|
300
|
+
|
301
|
+
it "should not use dperecated ActiveModel options" do
|
302
|
+
ActiveSupport::Deprecation.should_not_receive(:warn)
|
303
|
+
@cat.should_not be_valid
|
304
|
+
end
|
287
305
|
end
|
288
306
|
|
289
307
|
describe "on a casted model property" do
|
@@ -423,15 +441,15 @@ describe CouchRest::Model::CastedModel do
|
|
423
441
|
end
|
424
442
|
|
425
443
|
describe "validate" do
|
426
|
-
it "should run
|
427
|
-
@model.
|
444
|
+
it "should run before_validation before validating" do
|
445
|
+
@model.run_before_validation.should be_nil
|
428
446
|
@model.should be_valid
|
429
|
-
@model.
|
447
|
+
@model.run_before_validation.should be_true
|
430
448
|
end
|
431
|
-
it "should run
|
432
|
-
@model.
|
449
|
+
it "should run after_validation after validating" do
|
450
|
+
@model.run_after_validation.should be_nil
|
433
451
|
@model.should be_valid
|
434
|
-
@model.
|
452
|
+
@model.run_after_validation.should be_true
|
435
453
|
end
|
436
454
|
end
|
437
455
|
end
|
@@ -85,12 +85,12 @@ describe "Proxy Class" do
|
|
85
85
|
end
|
86
86
|
it "should get first" do
|
87
87
|
u = @us.first
|
88
|
-
u.
|
88
|
+
u.should == @us.all.first
|
89
89
|
end
|
90
90
|
|
91
91
|
it "should get last" do
|
92
92
|
u = @us.last
|
93
|
-
u.
|
93
|
+
u.should == @us.all.last
|
94
94
|
end
|
95
95
|
|
96
96
|
it "should set database on first retreived document" do
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
2
|
+
require File.join(FIXTURE_PATH, 'more', 'article')
|
3
|
+
|
4
|
+
describe "Collections" do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
reset_test_db!
|
8
|
+
Article.refresh_design_doc
|
9
|
+
titles = ["very uniq one", "really interesting", "some fun",
|
10
|
+
"really awesome", "crazy bob", "this rocks", "super rad"]
|
11
|
+
titles.each_with_index do |title,i|
|
12
|
+
a = Article.new(:title => title, :date => Date.today)
|
13
|
+
a.save
|
14
|
+
end
|
15
|
+
|
16
|
+
titles = ["yesterday very uniq one", "yesterday really interesting", "yesterday some fun",
|
17
|
+
"yesterday really awesome", "yesterday crazy bob", "yesterday this rocks"]
|
18
|
+
titles.each_with_index do |title,i|
|
19
|
+
a = Article.new(:title => title, :date => Date.today - 1)
|
20
|
+
a.save
|
21
|
+
end
|
22
|
+
end
|
23
|
+
it "should return a proxy that looks like an array of 7 Article objects" do
|
24
|
+
articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
|
25
|
+
:key => Date.today, :include_docs => true)
|
26
|
+
articles.class.should == Array
|
27
|
+
articles.size.should == 7
|
28
|
+
end
|
29
|
+
it "should provide a class method for paginate" do
|
30
|
+
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
31
|
+
:per_page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
32
|
+
articles.size.should == 3
|
33
|
+
|
34
|
+
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
35
|
+
:per_page => 3, :page => 2, :descending => true, :key => Date.today, :include_docs => true)
|
36
|
+
articles.size.should == 3
|
37
|
+
|
38
|
+
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
39
|
+
:per_page => 3, :page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
40
|
+
articles.size.should == 1
|
41
|
+
end
|
42
|
+
it "should provide a class method for paginated_each" do
|
43
|
+
options = { :design_doc => 'Article', :view_name => 'by_date',
|
44
|
+
:per_page => 3, :page => 1, :descending => true, :key => Date.today,
|
45
|
+
:include_docs => true }
|
46
|
+
Article.paginated_each(options) do |a|
|
47
|
+
a.should_not be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
it "should provide a class method to get a collection for a view" do
|
51
|
+
articles = Article.find_all_article_details(:key => Date.today)
|
52
|
+
articles.class.should == Array
|
53
|
+
articles.size.should == 7
|
54
|
+
end
|
55
|
+
it "should get a subset of articles using paginate" do
|
56
|
+
articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
|
57
|
+
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
58
|
+
articles.paginate(:page => 2, :per_page => 3).size.should == 3
|
59
|
+
articles.paginate(:page => 3, :per_page => 3).size.should == 1
|
60
|
+
end
|
61
|
+
it "should get all articles, a few at a time, using paginated each" do
|
62
|
+
articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
|
63
|
+
articles.paginated_each(:per_page => 3) do |a|
|
64
|
+
a.should_not be_nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should raise an exception if design_doc is not provided" do
|
69
|
+
lambda{Article.collection_proxy_for(nil, 'by_date')}.should raise_error
|
70
|
+
lambda{Article.paginate(:view_name => 'by_date')}.should raise_error
|
71
|
+
end
|
72
|
+
it "should raise an exception if view_name is not provided" do
|
73
|
+
lambda{Article.collection_proxy_for('Article', nil)}.should raise_error
|
74
|
+
lambda{Article.paginate(:design_doc => 'Article')}.should raise_error
|
75
|
+
end
|
76
|
+
it "should be able to span multiple keys" do
|
77
|
+
articles = Article.collection_proxy_for('Article', 'by_date', :startkey => Date.today - 1, :endkey => Date.today, :include_docs => true)
|
78
|
+
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
79
|
+
articles.paginate(:page => 3, :per_page => 3).size.should == 3
|
80
|
+
articles.paginate(:page => 5, :per_page => 3).size.should == 1
|
81
|
+
end
|
82
|
+
it "should pass database parameter to pager" do
|
83
|
+
proxy = mock(:proxy)
|
84
|
+
proxy.stub!(:paginate)
|
85
|
+
::CouchRest::Model::Collection::CollectionProxy.should_receive(:new).with('database', anything(), anything(), anything(), anything()).and_return(proxy)
|
86
|
+
Article.paginate(:design_doc => 'Article', :view_name => 'by_date', :database => 'database')
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|