couch_potato 0.6.0 → 0.7.0.pre.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/.gitignore +0 -1
- data/.travis.yml +9 -1
- data/CHANGES.md +12 -0
- data/Gemfile.lock +29 -23
- data/MIT-LICENSE.txt +1 -1
- data/README.md +68 -38
- data/Rakefile +19 -60
- data/active_support_3_0.lock +4 -0
- data/active_support_3_1.lock +4 -0
- data/active_support_3_2 +4 -0
- data/active_support_3_2.lock +55 -0
- data/couch_potato.gemspec +1 -0
- data/lib/couch_potato/database.rb +55 -27
- data/lib/couch_potato/persistence/active_model_compliance.rb +6 -2
- data/lib/couch_potato/persistence/callbacks.rb +0 -1
- data/lib/couch_potato/persistence/dirty_attributes.rb +8 -17
- data/lib/couch_potato/persistence/json.rb +3 -2
- data/lib/couch_potato/persistence/properties.rb +19 -8
- data/lib/couch_potato/persistence/simple_property.rb +1 -3
- data/lib/couch_potato/persistence/type_caster.rb +7 -2
- data/lib/couch_potato/persistence.rb +27 -13
- data/lib/couch_potato/railtie.rb +1 -1
- data/lib/couch_potato/rspec/matchers/list_as_matcher.rb +12 -12
- data/lib/couch_potato/rspec/matchers/map_to_matcher.rb +8 -8
- data/lib/couch_potato/rspec/matchers/reduce_to_matcher.rb +10 -10
- data/lib/couch_potato/rspec/matchers.rb +8 -7
- data/lib/couch_potato/validation.rb +15 -11
- data/lib/couch_potato/version.rb +1 -1
- data/lib/couch_potato/view/base_view_spec.rb +14 -12
- data/lib/couch_potato/view/model_view_spec.rb +134 -39
- data/lib/couch_potato/view/properties_view_spec.rb +11 -7
- data/lib/couch_potato/view/view_query.rb +10 -9
- data/lib/couch_potato.rb +25 -10
- data/spec/callbacks_spec.rb +88 -0
- data/spec/create_spec.rb +22 -4
- data/spec/default_property_spec.rb +6 -0
- data/spec/property_spec.rb +81 -44
- data/spec/railtie_spec.rb +20 -18
- data/spec/spec_helper.rb +19 -1
- data/spec/unit/active_model_compliance_spec.rb +17 -11
- data/spec/unit/attributes_spec.rb +33 -10
- data/spec/unit/base_view_spec_spec.rb +19 -5
- data/spec/unit/couch_potato_spec.rb +1 -20
- data/spec/unit/create_spec.rb +2 -2
- data/spec/unit/database_spec.rb +113 -47
- data/spec/unit/dirty_attributes_spec.rb +19 -19
- data/spec/unit/model_view_spec_spec.rb +78 -1
- data/spec/unit/properties_view_spec_spec.rb +18 -5
- data/spec/unit/validation_spec.rb +1 -55
- data/spec/unit/view_query_spec.rb +48 -26
- data/spec/{custom_view_spec.rb → views_spec.rb} +59 -17
- metadata +88 -90
- data/.rvmrc +0 -1
- data/lib/core_ext/object.rb +0 -5
- data/lib/core_ext/string.rb +0 -12
- data/lib/core_ext/symbol.rb +0 -15
- data/lib/couch_potato/validation/with_active_model.rb +0 -27
- data/lib/couch_potato/validation/with_validatable.rb +0 -41
@@ -35,11 +35,11 @@ module CouchPotato
|
|
35
35
|
# For your convenience when passing a hash with only a key parameter you can just pass in the value
|
36
36
|
#
|
37
37
|
# db.view(User.all(key: 1)) == db.view(User.all(1))
|
38
|
-
#
|
38
|
+
#
|
39
39
|
# Instead of passing a startkey and endkey you can pass in a key with a range:
|
40
40
|
#
|
41
41
|
# db.view(User.all(key: 1..20)) == db.view(startkey: 1, endkey: 20) == db.view(User.all(1..20))
|
42
|
-
#
|
42
|
+
#
|
43
43
|
# You can also pass in multiple keys:
|
44
44
|
#
|
45
45
|
# db.view(User.all(keys: [1, 2, 3]))
|
@@ -51,7 +51,8 @@ module CouchPotato
|
|
51
51
|
:map => spec.map_function,
|
52
52
|
:reduce => spec.reduce_function}
|
53
53
|
},
|
54
|
-
({spec.list_name => spec.list_function} unless spec.list_name.nil?)
|
54
|
+
({spec.list_name => spec.list_function} unless spec.list_name.nil?),
|
55
|
+
spec.language
|
55
56
|
).query_view!(spec.view_parameters)
|
56
57
|
processed_results = spec.process_results results
|
57
58
|
processed_results.instance_eval "def total_rows; #{results['total_rows']}; end" if results['total_rows']
|
@@ -60,12 +61,12 @@ module CouchPotato
|
|
60
61
|
end if processed_results.respond_to?(:each)
|
61
62
|
processed_results
|
62
63
|
end
|
63
|
-
|
64
|
+
|
64
65
|
# returns the first result from a #view query or nil
|
65
66
|
def first(spec)
|
66
67
|
view(spec).first
|
67
68
|
end
|
68
|
-
|
69
|
+
|
69
70
|
# returns th first result from a #view or raises CouchPotato::NotFound
|
70
71
|
def first!(spec)
|
71
72
|
first(spec) || raise(CouchPotato::NotFound)
|
@@ -81,7 +82,7 @@ module CouchPotato
|
|
81
82
|
end
|
82
83
|
end
|
83
84
|
alias_method :save, :save_document
|
84
|
-
|
85
|
+
|
85
86
|
# saves a document, raises a CouchPotato::Database::ValidationsFailedError on failure
|
86
87
|
def save_document!(document)
|
87
88
|
save_document(document) || raise(ValidationsFailedError.new(document.errors.full_messages))
|
@@ -98,27 +99,43 @@ module CouchPotato
|
|
98
99
|
end
|
99
100
|
alias_method :destroy, :destroy_document
|
100
101
|
|
101
|
-
# loads a document by its id
|
102
|
+
# loads a document by its id(s)
|
103
|
+
# id - either a single id or an array of ids
|
104
|
+
# returns either a single document or an array of documents (if an array of ids was passed).
|
105
|
+
# returns nil if the single document could not be found. when passing an array and some documents
|
106
|
+
# could not be found these are omitted from the returned array
|
102
107
|
def load_document(id)
|
103
108
|
raise "Can't load a document without an id (got nil)" if id.nil?
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
109
|
+
|
110
|
+
if id.is_a?(Array)
|
111
|
+
bulk_load id
|
112
|
+
else
|
113
|
+
begin
|
114
|
+
instance = couchrest_database.get(id)
|
115
|
+
instance.database = self
|
116
|
+
instance
|
117
|
+
rescue(RestClient::ResourceNotFound)
|
118
|
+
nil
|
119
|
+
end
|
110
120
|
end
|
111
121
|
end
|
112
122
|
alias_method :load, :load_document
|
113
|
-
|
123
|
+
|
124
|
+
# loads one or more documents by its id(s)
|
125
|
+
# behaves like #load except it raises a CouchPotato::NotFound if any of the documents could not be found
|
114
126
|
def load!(id)
|
115
|
-
load(id)
|
127
|
+
doc = load(id)
|
128
|
+
if id.is_a?(Array)
|
129
|
+
missing_docs = id - doc.map(&:id)
|
130
|
+
end
|
131
|
+
raise(CouchPotato::NotFound, missing_docs.try(:join, ', ')) if doc.nil? || missing_docs.try(:any?)
|
132
|
+
doc
|
116
133
|
end
|
117
134
|
|
118
135
|
def inspect #:nodoc:
|
119
136
|
"#<CouchPotato::Database @root=\"#{couchrest_database.root}\">"
|
120
137
|
end
|
121
|
-
|
138
|
+
|
122
139
|
# returns the underlying CouchRest::Database instance
|
123
140
|
def couchrest_database
|
124
141
|
@couchrest_database
|
@@ -126,20 +143,27 @@ module CouchPotato
|
|
126
143
|
|
127
144
|
private
|
128
145
|
|
146
|
+
def bulk_load(ids)
|
147
|
+
response = couchrest_database.bulk_load ids
|
148
|
+
existing_rows = response['rows'].select{|row| row.key? 'doc'}
|
149
|
+
docs = existing_rows.map{|row| row["doc"]}
|
150
|
+
docs.each{|doc| doc.database = self}
|
151
|
+
end
|
152
|
+
|
129
153
|
def create_document(document, validate)
|
130
154
|
document.database = self
|
131
|
-
|
155
|
+
|
132
156
|
if validate
|
133
157
|
document.errors.clear
|
134
|
-
document.run_callbacks
|
135
|
-
document.run_callbacks
|
158
|
+
return false if false == document.run_callbacks(:validation_on_save) do
|
159
|
+
return false if false == document.run_callbacks(:validation_on_create) do
|
136
160
|
return false unless valid_document?(document)
|
137
161
|
end
|
138
162
|
end
|
139
163
|
end
|
140
|
-
|
141
|
-
document.run_callbacks
|
142
|
-
document.run_callbacks
|
164
|
+
|
165
|
+
return false if false == document.run_callbacks(:save) do
|
166
|
+
return false if false == document.run_callbacks(:create) do
|
143
167
|
res = couchrest_database.save_doc document.to_hash
|
144
168
|
document._rev = res['rev']
|
145
169
|
document._id = res['id']
|
@@ -151,15 +175,15 @@ module CouchPotato
|
|
151
175
|
def update_document(document, validate)
|
152
176
|
if validate
|
153
177
|
document.errors.clear
|
154
|
-
document.run_callbacks
|
155
|
-
document.run_callbacks
|
178
|
+
return false if false == document.run_callbacks(:validation_on_save) do
|
179
|
+
return false if false == document.run_callbacks(:validation_on_update) do
|
156
180
|
return false unless valid_document?(document)
|
157
181
|
end
|
158
182
|
end
|
159
183
|
end
|
160
184
|
|
161
|
-
document.run_callbacks
|
162
|
-
document.run_callbacks
|
185
|
+
return false if false == document.run_callbacks(:save) do
|
186
|
+
return false if false == document.run_callbacks(:update) do
|
163
187
|
res = couchrest_database.save_doc document.to_hash
|
164
188
|
document._rev = res['rev']
|
165
189
|
end
|
@@ -172,7 +196,11 @@ module CouchPotato
|
|
172
196
|
errors.instance_variable_set("@messages", errors.messages.dup) if errors.respond_to?(:messages)
|
173
197
|
document.valid?
|
174
198
|
errors.each do |k, v|
|
175
|
-
|
199
|
+
if v.respond_to?(:each)
|
200
|
+
v.each {|message| document.errors.add(k, message)}
|
201
|
+
else
|
202
|
+
document.errors.add(k, v)
|
203
|
+
end
|
176
204
|
end
|
177
205
|
document.errors.empty?
|
178
206
|
end
|
@@ -12,14 +12,18 @@ module CouchPotato
|
|
12
12
|
self
|
13
13
|
end
|
14
14
|
|
15
|
+
def to_partial_path
|
16
|
+
"#{self.class.name.underscore.pluralize}/#{self.class.name.underscore}"
|
17
|
+
end
|
18
|
+
|
15
19
|
def errors
|
16
20
|
super || {}
|
17
21
|
end
|
18
|
-
|
22
|
+
|
19
23
|
def persisted?
|
20
24
|
!self.new?
|
21
25
|
end
|
22
|
-
|
26
|
+
|
23
27
|
def to_key
|
24
28
|
persisted? ? [to_param] : nil
|
25
29
|
end
|
@@ -12,7 +12,6 @@ module CouchPotato
|
|
12
12
|
|
13
13
|
define_model_callbacks :create, :save, :update, :destroy
|
14
14
|
define_model_callbacks *[:save, :create, :update].map {|c| :"validation_on_#{c}"}
|
15
|
-
define_model_callbacks :validation unless Config.validation_framework == :active_model
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
@@ -2,45 +2,36 @@ require 'bigdecimal'
|
|
2
2
|
module CouchPotato
|
3
3
|
module Persistence
|
4
4
|
module DirtyAttributes
|
5
|
-
|
5
|
+
|
6
6
|
def self.included(base) #:nodoc:
|
7
7
|
base.send :include, ActiveModel::Dirty
|
8
8
|
base.class_eval do
|
9
9
|
after_save :reset_dirty_attributes
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def initialize(attributes = {})
|
14
14
|
super
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
# returns true if a model has dirty attributes, i.e. their value has changed since the last save
|
18
|
-
def dirty?
|
18
|
+
def dirty?
|
19
19
|
changed? || @forced_dirty
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
# marks a model as dirty
|
23
23
|
def is_dirty
|
24
24
|
@forced_dirty = true
|
25
25
|
end
|
26
|
-
|
27
|
-
def method_missing(name, *args)
|
28
|
-
if(name.to_s.include?('_will_change!'))
|
29
|
-
self.class.define_attribute_methods self.class.property_names
|
30
|
-
send(name, *args)
|
31
|
-
else
|
32
|
-
super
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
26
|
+
|
36
27
|
private
|
37
|
-
|
28
|
+
|
38
29
|
def reset_dirty_attributes
|
39
30
|
@previously_changed = changes
|
40
31
|
@changed_attributes.clear
|
41
32
|
@forced_dirty = nil
|
42
33
|
end
|
43
|
-
|
34
|
+
|
44
35
|
def clone_attribute(value)
|
45
36
|
if [Fixnum, Symbol, TrueClass, FalseClass, NilClass, Float, BigDecimal].include?(value.class)
|
46
37
|
value
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
|
1
3
|
module CouchPotato
|
2
4
|
module Persistence
|
3
5
|
module Json
|
@@ -39,10 +41,9 @@ module CouchPotato
|
|
39
41
|
# creates a model instance from JSON
|
40
42
|
def json_create(json)
|
41
43
|
return if json.nil?
|
42
|
-
instance = self.new
|
44
|
+
instance = self.new :_document => HashWithIndifferentAccess.new(json)
|
43
45
|
instance._id = json[:_id] || json['_id']
|
44
46
|
instance._rev = json[:_rev] || json['_rev']
|
45
|
-
instance._document = json
|
46
47
|
instance
|
47
48
|
end
|
48
49
|
end
|
@@ -5,22 +5,22 @@ module CouchPotato
|
|
5
5
|
module Properties
|
6
6
|
class PropertyList
|
7
7
|
include Enumerable
|
8
|
-
|
8
|
+
|
9
9
|
attr_accessor :list
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(clazz)
|
12
12
|
@clazz = clazz
|
13
13
|
@list = []
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def each
|
17
17
|
(list + inherited_properties).each {|property| yield property}
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def <<(property)
|
21
21
|
@list << property
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def inherited_properties
|
25
25
|
superclazz = @clazz.superclass
|
26
26
|
properties = []
|
@@ -31,7 +31,7 @@ module CouchPotato
|
|
31
31
|
properties.flatten
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def self.included(base) #:nodoc:
|
36
36
|
base.extend ClassMethods
|
37
37
|
base.class_eval do
|
@@ -41,11 +41,11 @@ module CouchPotato
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def type_caster #:nodoc:
|
46
46
|
@type_caster ||= TypeCaster.new
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
module ClassMethods
|
50
50
|
# returns all the property names of a model class that have been defined using the #property method
|
51
51
|
#
|
@@ -70,9 +70,20 @@ module CouchPotato
|
|
70
70
|
# property :publisher, :type => Publisher
|
71
71
|
# end
|
72
72
|
def property(name, options = {})
|
73
|
+
undefine_attribute_methods
|
74
|
+
define_attribute_methods property_names + [name]
|
73
75
|
properties << SimpleProperty.new(self, name, options)
|
76
|
+
remove_attribute_accessors_from_activesupport_module
|
74
77
|
end
|
75
78
|
|
79
|
+
def remove_attribute_accessors_from_activesupport_module
|
80
|
+
active_support_module = ancestors[1..-1].find{|m| m.name.nil? && (property_names - m.instance_methods).empty?}
|
81
|
+
if active_support_module
|
82
|
+
property_names.each do |name|
|
83
|
+
active_support_module.send :remove_method, name if active_support_module.instance_methods.include?(name)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
76
87
|
end
|
77
88
|
end
|
78
89
|
end
|
@@ -52,12 +52,10 @@ module CouchPotato
|
|
52
52
|
|
53
53
|
def define_accessors(base, name, options)
|
54
54
|
base.class_eval do
|
55
|
-
include PropertyMethods
|
56
|
-
|
57
55
|
define_method "#{name}" do
|
58
56
|
load_attribute_from_document(name) unless instance_variable_defined?("@#{name}")
|
59
57
|
value = instance_variable_get("@#{name}")
|
60
|
-
if value.nil? && options[:default]
|
58
|
+
if value.nil? && !options[:default].nil?
|
61
59
|
default = clone_attribute(options[:default])
|
62
60
|
self.instance_variable_set("@#{name}", default)
|
63
61
|
default
|
@@ -1,9 +1,14 @@
|
|
1
1
|
module CouchPotato
|
2
2
|
module Persistence
|
3
3
|
class TypeCaster #:nodoc:
|
4
|
+
NUMBER_REGEX = /-?\d+\.?\d*/
|
5
|
+
|
4
6
|
def cast(value, type)
|
5
7
|
if type == :boolean
|
6
8
|
cast_boolean(value)
|
9
|
+
elsif type.instance_of?(Array)
|
10
|
+
nested_type = type.first
|
11
|
+
value.map { |val| cast_native(val, nested_type) } if value
|
7
12
|
else
|
8
13
|
cast_native(value, type)
|
9
14
|
end
|
@@ -24,9 +29,9 @@ module CouchPotato
|
|
24
29
|
def cast_native(value, type)
|
25
30
|
if type && !value.instance_of?(type)
|
26
31
|
if type == Fixnum
|
27
|
-
value.to_s.scan(
|
32
|
+
BigDecimal.new(value.to_s.scan(NUMBER_REGEX).join).round unless value.blank?
|
28
33
|
elsif type == Float
|
29
|
-
value.to_s.scan(
|
34
|
+
value.to_s.scan(NUMBER_REGEX).join.to_f unless value.blank?
|
30
35
|
else
|
31
36
|
type.json_create value unless value.blank?
|
32
37
|
end
|
@@ -16,7 +16,7 @@ require File.dirname(__FILE__) + '/view/view_query'
|
|
16
16
|
|
17
17
|
module CouchPotato
|
18
18
|
module Persistence
|
19
|
-
|
19
|
+
|
20
20
|
def self.included(base) #:nodoc:
|
21
21
|
base.send :include, Properties, Callbacks, Json, CouchPotato::View::CustomViews, CouchPotato::View::Lists
|
22
22
|
base.send :include, DirtyAttributes, GhostAttributes, Attachments
|
@@ -27,15 +27,15 @@ module CouchPotato
|
|
27
27
|
alias_method :id, :_id
|
28
28
|
alias_method :id=, :_id=
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
CouchPotato.models << base
|
32
32
|
end
|
33
33
|
|
34
34
|
# initialize a new instance of the model optionally passing it a hash of attributes.
|
35
35
|
# the attributes have to be declared using the #property method.
|
36
36
|
# the new model will be yielded to an optionally given block.
|
37
|
-
#
|
38
|
-
# example:
|
37
|
+
#
|
38
|
+
# example:
|
39
39
|
# class Book
|
40
40
|
# include CouchPotato::Persistence
|
41
41
|
# property :title
|
@@ -50,13 +50,15 @@ module CouchPotato
|
|
50
50
|
# book.title # => 'Time to Relax'
|
51
51
|
def initialize(attributes = {})
|
52
52
|
if attributes
|
53
|
+
@skip_dirty_tracking = true
|
53
54
|
attributes.each do |name, value|
|
54
55
|
self.send("#{name}=", value)
|
55
56
|
end
|
57
|
+
@skip_dirty_tracking = false
|
56
58
|
end
|
57
59
|
yield self if block_given?
|
58
60
|
end
|
59
|
-
|
61
|
+
|
60
62
|
# assign multiple attributes at once.
|
61
63
|
# the attributes have to be declared using the #property method
|
62
64
|
#
|
@@ -75,7 +77,7 @@ module CouchPotato
|
|
75
77
|
self.send "#{attribute}=", value
|
76
78
|
end
|
77
79
|
end
|
78
|
-
|
80
|
+
|
79
81
|
# returns all of a model's attributes that have been defined using the #property method as a Hash
|
80
82
|
#
|
81
83
|
# example:
|
@@ -92,35 +94,47 @@ module CouchPotato
|
|
92
94
|
res
|
93
95
|
end
|
94
96
|
end
|
95
|
-
|
97
|
+
|
98
|
+
def []=(attribute, value)
|
99
|
+
send "#{attribute}=", value
|
100
|
+
end
|
101
|
+
|
102
|
+
def [](attribute)
|
103
|
+
send(attribute)
|
104
|
+
end
|
105
|
+
|
106
|
+
def has_key?(key)
|
107
|
+
attributes.has_key?(key)
|
108
|
+
end
|
109
|
+
|
96
110
|
# returns true if a model hasn't been saved yet, false otherwise
|
97
111
|
def new?
|
98
112
|
_rev.nil?
|
99
113
|
end
|
100
114
|
alias_method :new_record?, :new?
|
101
|
-
|
115
|
+
|
102
116
|
# returns the document id
|
103
117
|
# this is used by rails to construct URLs
|
104
118
|
# can be overridden to for example use slugs for URLs instead if ids
|
105
119
|
def to_param
|
106
120
|
_id
|
107
121
|
end
|
108
|
-
|
122
|
+
|
109
123
|
def ==(other) #:nodoc:
|
110
124
|
other.class == self.class && self.to_json == other.to_json
|
111
125
|
end
|
112
|
-
|
126
|
+
|
113
127
|
def eql?(other)
|
114
128
|
self == other
|
115
129
|
end
|
116
|
-
|
130
|
+
|
117
131
|
def hash
|
118
132
|
_id.hash * (_id.hash.to_s.size ** 10) + _rev.hash
|
119
133
|
end
|
120
|
-
|
134
|
+
|
121
135
|
def inspect
|
122
136
|
attributes_as_string = attributes.map {|attribute, value| "#{attribute}: #{value.inspect}"}.join(", ")
|
123
137
|
%Q{#<#{self.class} _id: "#{_id}", _rev: "#{_rev}", #{attributes_as_string}>}
|
124
138
|
end
|
125
|
-
end
|
139
|
+
end
|
126
140
|
end
|
data/lib/couch_potato/railtie.rb
CHANGED
@@ -8,8 +8,8 @@ module CouchPotato
|
|
8
8
|
CouchPotato::Config.database_name = config
|
9
9
|
else
|
10
10
|
CouchPotato::Config.database_name = config['database']
|
11
|
-
CouchPotato::Config.validation_framework = config['validation_framework'] if config['validation_framework']
|
12
11
|
CouchPotato::Config.split_design_documents_per_view = config['split_design_documents_per_view'] if config['split_design_documents_per_view']
|
12
|
+
CouchPotato::Config.default_language = config['default_language'] if config['default_language']
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -4,20 +4,20 @@ module CouchPotato
|
|
4
4
|
def initialize(results_ruby)
|
5
5
|
@results_ruby = results_ruby
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def as(expected_ruby)
|
9
9
|
ListAsMatcher.new(expected_ruby, @results_ruby)
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
class ListAsMatcher
|
14
14
|
include RunJS
|
15
|
-
|
15
|
+
|
16
16
|
def initialize(expected_ruby, results_ruby)
|
17
17
|
@expected_ruby = expected_ruby
|
18
18
|
@results_ruby = results_ruby
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def matches?(view_spec)
|
22
22
|
js = <<-JS
|
23
23
|
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
@@ -25,7 +25,7 @@ module CouchPotato
|
|
25
25
|
var results = #{@results_ruby.to_json};
|
26
26
|
var listed = '';
|
27
27
|
var list = #{view_spec.list_function};
|
28
|
-
|
28
|
+
|
29
29
|
var getRow = function() {
|
30
30
|
return results.rows.shift();
|
31
31
|
};
|
@@ -33,22 +33,22 @@ module CouchPotato
|
|
33
33
|
listed = listed + text;
|
34
34
|
};
|
35
35
|
list();
|
36
|
-
|
36
|
+
print_r(JSON.parse(listed));
|
37
37
|
JS
|
38
|
-
|
38
|
+
|
39
39
|
@actual_ruby = JSON.parse(run_js(js))
|
40
|
-
|
40
|
+
|
41
41
|
@expected_ruby == @actual_ruby
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def failure_message_for_should
|
45
45
|
"Expected to list as #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def failure_message_for_should_not
|
49
49
|
"Expected to not list as #{@expected_ruby.inspect} but did."
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
end
|
53
53
|
end
|
54
|
-
end
|
54
|
+
end
|
@@ -7,20 +7,20 @@ module CouchPotato
|
|
7
7
|
def initialize(input_ruby)
|
8
8
|
@input_ruby = input_ruby
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def to(*expected_ruby)
|
12
12
|
MapToMatcher.new(expected_ruby, @input_ruby)
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
class MapToMatcher
|
17
17
|
include RunJS
|
18
|
-
|
18
|
+
|
19
19
|
def initialize(expected_ruby, input_ruby)
|
20
20
|
@expected_ruby = expected_ruby
|
21
21
|
@input_ruby = input_ruby
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def matches?(view_spec)
|
25
25
|
js = <<-JS
|
26
26
|
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
@@ -31,19 +31,19 @@ module CouchPotato
|
|
31
31
|
result.push([key, value]);
|
32
32
|
};
|
33
33
|
map(doc);
|
34
|
-
|
34
|
+
print_r(result);
|
35
35
|
JS
|
36
36
|
@actual_ruby = JSON.parse(run_js(js))
|
37
37
|
@expected_ruby == @actual_ruby
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
def failure_message_for_should
|
41
41
|
"Expected to map to #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def failure_message_for_should_not
|
45
45
|
"Expected not to map to #{@actual_ruby.inspect} but did."
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
|
-
end
|
49
|
+
end
|
@@ -4,23 +4,23 @@ module CouchPotato
|
|
4
4
|
def initialize(docs, keys, rereduce = false)
|
5
5
|
@docs, @keys, @rereduce = docs, keys, rereduce
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def to(expected_ruby)
|
9
9
|
ReduceToMatcher.new(expected_ruby, @docs, @keys, @rereduce)
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
class ReduceToMatcher
|
14
14
|
include RunJS
|
15
|
-
|
15
|
+
|
16
16
|
def initialize(expected_ruby, docs, keys, rereduce = false)
|
17
17
|
@expected_ruby, @docs, @keys, @rereduce = expected_ruby, docs, keys, rereduce
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def matches?(view_spec)
|
21
21
|
js = <<-JS
|
22
22
|
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
23
|
-
|
23
|
+
|
24
24
|
sum = function(values) {
|
25
25
|
var rv = 0;
|
26
26
|
for (var i in values) {
|
@@ -28,23 +28,23 @@ module CouchPotato
|
|
28
28
|
}
|
29
29
|
return rv;
|
30
30
|
};
|
31
|
-
|
31
|
+
|
32
32
|
var docs = #{@docs.to_json};
|
33
33
|
var keys = #{@keys.to_json};
|
34
34
|
var reduce = #{view_spec.reduce_function};
|
35
|
-
|
35
|
+
print_r({result: reduce(docs, keys, #{@rereduce})});
|
36
36
|
JS
|
37
37
|
@actual_ruby = JSON.parse(run_js(js))['result']
|
38
38
|
@expected_ruby == @actual_ruby
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def failure_message_for_should
|
42
42
|
"Expected to reduce to #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def failure_message_for_should_not
|
46
46
|
"Expected not to reduce to #{@actual_ruby.inspect} but did."
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
|
-
end
|
50
|
+
end
|