couch_potato 0.2.12 → 0.2.13
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.md +8 -0
- data/README.md +33 -4
- data/VERSION.yml +2 -2
- data/lib/couch_potato/database.rb +31 -14
- data/lib/couch_potato/persistence/json.rb +1 -1
- data/lib/couch_potato/persistence/properties.rb +30 -1
- data/lib/couch_potato/persistence/simple_property.rb +5 -5
- data/lib/couch_potato/persistence/validation.rb +7 -1
- data/lib/couch_potato/rspec/matchers/map_to_matcher.rb +125 -0
- data/lib/couch_potato/rspec/matchers/print_r.js +60 -0
- data/lib/couch_potato/rspec/matchers/reduce_to_matcher.rb +6 -0
- data/lib/couch_potato/rspec/matchers.rb +2 -0
- data/lib/couch_potato/view/custom_view_spec.rb +5 -1
- data/lib/couch_potato/view/custom_views.rb +12 -3
- data/lib/couch_potato/view/model_view_spec.rb +1 -3
- data/lib/couch_potato/view/view_query.rb +1 -1
- data/lib/couch_potato.rb +2 -1
- data/spec/attachments_spec.rb +1 -1
- data/spec/callbacks_spec.rb +34 -0
- data/spec/create_spec.rb +1 -1
- data/spec/custom_view_spec.rb +17 -0
- data/spec/fixtures/person.rb +2 -2
- data/spec/property_spec.rb +55 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/database_spec.rb +164 -7
- data/spec/unit/dirty_attributes_spec.rb +3 -3
- data/spec/unit/json_create_id_spec.rb +14 -0
- data/spec/unit/rspec_matchers_spec.rb +97 -0
- data/spec/update_spec.rb +1 -1
- metadata +10 -2
data/CHANGES.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## Changes
|
2
2
|
|
3
|
+
### 0.2.13
|
4
|
+
|
5
|
+
* support adding errors in before_validation callbacks (mattmatt)
|
6
|
+
* support for inheritance (mattmatt)
|
7
|
+
* support for save without validations (mattmatt)
|
8
|
+
* improved (de)serialization now supports deserializing nested objects (railsbros, specs by hagenburger)
|
9
|
+
* RSpec matchers for testing map/reduce functions (langalex)
|
10
|
+
|
3
11
|
### 0.2.10
|
4
12
|
* fixed bug with hardcoded timezone
|
5
13
|
|
data/README.md
CHANGED
@@ -22,13 +22,11 @@ Lastly Couch Potato aims to provide a seamless integration with Ruby on Rails, e
|
|
22
22
|
|
23
23
|
Couch Potato is hosted as a gem on github which you can install like this:
|
24
24
|
|
25
|
-
sudo gem
|
26
|
-
sudo gem install langalex-couch_potato
|
25
|
+
sudo gem install couch_potato --source http://gemcutter.org
|
27
26
|
|
28
27
|
#### Using with your ruby application:
|
29
28
|
|
30
29
|
require 'rubygems'
|
31
|
-
gem 'langalex-couch_potato'
|
32
30
|
require 'couch_potato'
|
33
31
|
|
34
32
|
Alternatively you can download or clone the source repository and then require lib/couch_potato.rb.
|
@@ -45,7 +43,8 @@ The server URL will default to http://localhost:5984/ unless specified:
|
|
45
43
|
|
46
44
|
Add to your config/environment.rb:
|
47
45
|
|
48
|
-
config.gem '
|
46
|
+
config.gem 'couch_potato', :source => 'http://gemcutter.org'
|
47
|
+
config.frameworks -= [:active_record] # if you switch completely
|
49
48
|
|
50
49
|
Then create a config/couchdb.yml:
|
51
50
|
|
@@ -282,6 +281,36 @@ To make testing easier and faster database logic has been put into its own class
|
|
282
281
|
|
283
282
|
By creating you own instances of CouchPotato::Database and passing them a fake CouchRest database instance you can completely disconnect your unit tests/spec from the database.
|
284
283
|
|
284
|
+
##### Testing map/reduce functions
|
285
|
+
|
286
|
+
Couch Potato provides custom RSpec matchers for testing the map and reduce functions of your views. For example you can do this:
|
287
|
+
|
288
|
+
Class User
|
289
|
+
include CouchPotato::Persistence
|
290
|
+
|
291
|
+
view :by_name, :key => :name
|
292
|
+
view :by_age, :key => :age
|
293
|
+
end
|
294
|
+
|
295
|
+
#RSpec
|
296
|
+
describe User, 'by_name' do
|
297
|
+
it "should map users to their name" do
|
298
|
+
User.by_name.should map({:name => 'bill', :age => 23}).to([['bill', null]])
|
299
|
+
end
|
300
|
+
|
301
|
+
it "should reduce the users to the sum of their age" do
|
302
|
+
User.by_age.should reduce([], [[23], [22]]).to(45)
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should rereduce" do
|
306
|
+
User.by_age.should rereduce([], [[23], [22]]).to(45)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
This will actually run your map/reduce functions in a JavaScript interpreter, passing the arguments as JSON and converting the results back to Ruby.
|
311
|
+
|
312
|
+
In order for this to work you must have the `js` executable in your PATH. This is usually part of the _spidermonkey_ package/port. (On MacPorts that's _spidemonkey_, on Linux it could be one of _libjs_, _libmozjs_ or _libspidermonkey_). When you installed CouchDB via your packet manager Spidermonkey should already be there.
|
313
|
+
|
285
314
|
### Helping out
|
286
315
|
|
287
316
|
Please fix bugs, add more specs, implement new features by forking the github repo at http://github.com/langalex/couch_potato.
|
data/VERSION.yml
CHANGED
@@ -19,12 +19,13 @@ module CouchPotato
|
|
19
19
|
spec.process_results results
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
|
23
|
+
def save_document(document, validate = true)
|
23
24
|
return true unless document.dirty?
|
24
25
|
if document.new?
|
25
|
-
create_document
|
26
|
+
create_document(document, validate)
|
26
27
|
else
|
27
|
-
update_document
|
28
|
+
update_document(document, validate)
|
28
29
|
end
|
29
30
|
end
|
30
31
|
alias_method :save, :save_document
|
@@ -47,9 +48,7 @@ module CouchPotato
|
|
47
48
|
def load_document(id)
|
48
49
|
raise "Can't load a document without an id (got nil)" if id.nil?
|
49
50
|
begin
|
50
|
-
|
51
|
-
klass = json['ruby_class'].split('::').inject(Class){|scope, const| scope.const_get(const)}
|
52
|
-
instance = klass.json_create json
|
51
|
+
instance = database.get(id)
|
53
52
|
instance.database = self
|
54
53
|
instance
|
55
54
|
rescue(RestClient::ResourceNotFound)
|
@@ -70,11 +69,16 @@ module CouchPotato
|
|
70
69
|
end
|
71
70
|
end
|
72
71
|
|
73
|
-
def create_document(document)
|
72
|
+
def create_document(document, validate)
|
74
73
|
document.database = self
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
|
75
|
+
if validate
|
76
|
+
document.errors.clear
|
77
|
+
document.run_callbacks :before_validation_on_save
|
78
|
+
document.run_callbacks :before_validation_on_create
|
79
|
+
return false unless valid_document?(document)
|
80
|
+
end
|
81
|
+
|
78
82
|
document.run_callbacks :before_save
|
79
83
|
document.run_callbacks :before_create
|
80
84
|
res = database.save_doc clean_hash(document.to_hash)
|
@@ -85,10 +89,14 @@ module CouchPotato
|
|
85
89
|
true
|
86
90
|
end
|
87
91
|
|
88
|
-
def update_document(document)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
+
def update_document(document, validate)
|
93
|
+
if validate
|
94
|
+
document.errors.clear
|
95
|
+
document.run_callbacks :before_validation_on_save
|
96
|
+
document.run_callbacks :before_validation_on_update
|
97
|
+
return false unless valid_document?(document)
|
98
|
+
end
|
99
|
+
|
92
100
|
document.run_callbacks :before_save
|
93
101
|
document.run_callbacks :before_update
|
94
102
|
res = database.save_doc clean_hash(document.to_hash)
|
@@ -98,6 +106,15 @@ module CouchPotato
|
|
98
106
|
true
|
99
107
|
end
|
100
108
|
|
109
|
+
def valid_document?(document)
|
110
|
+
errors = document.errors.errors.dup
|
111
|
+
document.valid?
|
112
|
+
errors.each do |k, v|
|
113
|
+
v.each {|message| document.errors.add(k, message)}
|
114
|
+
end
|
115
|
+
document.errors.empty?
|
116
|
+
end
|
117
|
+
|
101
118
|
def database
|
102
119
|
@database
|
103
120
|
end
|
@@ -15,7 +15,7 @@ module CouchPotato
|
|
15
15
|
(self.class.properties).inject({}) do |props, property|
|
16
16
|
property.serialize(props, self)
|
17
17
|
props
|
18
|
-
end.merge(
|
18
|
+
end.merge(JSON.create_id => self.class.name).merge(id_and_rev_json)
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
@@ -3,12 +3,41 @@ require File.dirname(__FILE__) + '/simple_property'
|
|
3
3
|
module CouchPotato
|
4
4
|
module Persistence
|
5
5
|
module Properties
|
6
|
+
class PropertyList
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
attr_accessor :list
|
10
|
+
|
11
|
+
def initialize(clazz)
|
12
|
+
@clazz = clazz
|
13
|
+
@list = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def each
|
17
|
+
(list + inherited_properties).each {|property| yield property}
|
18
|
+
end
|
19
|
+
|
20
|
+
def <<(property)
|
21
|
+
@list << property
|
22
|
+
end
|
23
|
+
|
24
|
+
def inherited_properties
|
25
|
+
superclazz = @clazz.superclass
|
26
|
+
properties = []
|
27
|
+
while superclazz && superclazz.respond_to?(:properties)
|
28
|
+
properties << superclazz.properties.list
|
29
|
+
superclazz = superclazz.superclass
|
30
|
+
end
|
31
|
+
properties.flatten
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
6
35
|
def self.included(base)
|
7
36
|
base.extend ClassMethods
|
8
37
|
base.class_eval do
|
9
38
|
def self.properties
|
10
39
|
@properties ||= {}
|
11
|
-
@properties[
|
40
|
+
@properties[name] ||= PropertyList.new(self)
|
12
41
|
end
|
13
42
|
end
|
14
43
|
end
|
@@ -12,11 +12,11 @@ module CouchPotato
|
|
12
12
|
|
13
13
|
def build(object, json)
|
14
14
|
value = json[name.to_s] || json[name.to_sym]
|
15
|
-
typecast_value = if type
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
typecast_value = if type && !value.instance_of?(type)
|
16
|
+
type.json_create value
|
17
|
+
else
|
18
|
+
value
|
19
|
+
end
|
20
20
|
object.send "#{name}=", typecast_value
|
21
21
|
end
|
22
22
|
|
@@ -8,8 +8,14 @@ module CouchPotato
|
|
8
8
|
base.class_eval do
|
9
9
|
# Override the validate method to first run before_validation callback
|
10
10
|
def valid?
|
11
|
-
|
11
|
+
errors.clear
|
12
|
+
run_callbacks :before_validation
|
13
|
+
before_validation_errors = errors.errors.dup
|
12
14
|
super
|
15
|
+
before_validation_errors.each do |k, v|
|
16
|
+
v.each {|message| errors.add(k, message)}
|
17
|
+
end
|
18
|
+
errors.empty?
|
13
19
|
end
|
14
20
|
end
|
15
21
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Spec
|
4
|
+
module Matchers
|
5
|
+
def map(document)
|
6
|
+
CouchPotato::RSpec::MapToProxy.new(document)
|
7
|
+
end
|
8
|
+
|
9
|
+
def reduce(docs, keys)
|
10
|
+
CouchPotato::RSpec::ReduceToProxy.new(docs, keys)
|
11
|
+
end
|
12
|
+
|
13
|
+
def rereduce(docs, keys)
|
14
|
+
CouchPotato::RSpec::ReduceToProxy.new(docs, keys, true)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module CouchPotato
|
20
|
+
module RSpec
|
21
|
+
|
22
|
+
module RunJS
|
23
|
+
private
|
24
|
+
|
25
|
+
def run_js(js)
|
26
|
+
path = 'couch_potato_js_runner.js'
|
27
|
+
File.open(path, 'w') {|f| f << js}
|
28
|
+
`js #{path}`
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
class MapToProxy
|
34
|
+
def initialize(input_ruby)
|
35
|
+
@input_ruby = input_ruby
|
36
|
+
end
|
37
|
+
|
38
|
+
def to(expected_ruby)
|
39
|
+
MapToMatcher.new(expected_ruby, @input_ruby)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class MapToMatcher
|
44
|
+
include RunJS
|
45
|
+
|
46
|
+
def initialize(expected_ruby, input_ruby)
|
47
|
+
@expected_ruby = expected_ruby
|
48
|
+
@input_ruby = input_ruby
|
49
|
+
end
|
50
|
+
|
51
|
+
def matches?(view_spec)
|
52
|
+
js = <<-JS
|
53
|
+
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
54
|
+
var doc = #{@input_ruby.to_json};
|
55
|
+
var map = #{view_spec.map_function};
|
56
|
+
var result = [];
|
57
|
+
var emit = function(key, value) {
|
58
|
+
result.push([key, value]);
|
59
|
+
};
|
60
|
+
map(doc);
|
61
|
+
print(print_r(result));
|
62
|
+
JS
|
63
|
+
@actual_ruby = JSON.parse(run_js(js))
|
64
|
+
@expected_ruby == @actual_ruby
|
65
|
+
end
|
66
|
+
|
67
|
+
def failure_message_for_should
|
68
|
+
"Expected to map to #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
69
|
+
end
|
70
|
+
|
71
|
+
def failure_message_for_should_not
|
72
|
+
"Expected not to map to #{@actual_ruby.inspect} but did."
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class ReduceToProxy
|
77
|
+
def initialize(docs, keys, rereduce = false)
|
78
|
+
@docs, @keys, @rereduce = docs, keys, rereduce
|
79
|
+
end
|
80
|
+
|
81
|
+
def to(expected_ruby)
|
82
|
+
ReduceToMatcher.new(expected_ruby, @docs, @keys, @rereduce)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class ReduceToMatcher
|
87
|
+
include RunJS
|
88
|
+
|
89
|
+
def initialize(expected_ruby, docs, keys, rereduce = false)
|
90
|
+
@expected_ruby, @docs, @keys, @rereduce = expected_ruby, docs, keys, rereduce
|
91
|
+
end
|
92
|
+
|
93
|
+
def matches?(view_spec)
|
94
|
+
js = <<-JS
|
95
|
+
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
96
|
+
|
97
|
+
sum = function(values) {
|
98
|
+
var rv = 0;
|
99
|
+
for (var i in values) {
|
100
|
+
rv += values[i];
|
101
|
+
}
|
102
|
+
return rv;
|
103
|
+
};
|
104
|
+
|
105
|
+
var docs = #{@docs.to_json};
|
106
|
+
var keys = #{@keys.to_json};
|
107
|
+
var reduce = #{view_spec.reduce_function};
|
108
|
+
print(print_r({result: reduce(docs, keys, #{@rereduce})}));
|
109
|
+
JS
|
110
|
+
@actual_ruby = JSON.parse(run_js(js))['result']
|
111
|
+
@expected_ruby == @actual_ruby
|
112
|
+
end
|
113
|
+
|
114
|
+
def failure_message_for_should
|
115
|
+
"Expected to reduce to #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
116
|
+
end
|
117
|
+
|
118
|
+
def failure_message_for_should_not
|
119
|
+
"Expected not to reduce to #{@actual_ruby.inspect} but did."
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
// taken and adapted from http://scriptnode.com/article/javascript-print_r-or-var_dump-equivalent/
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Concatenates the values of a variable into an easily readable string
|
5
|
+
* by Matt Hackett [scriptnode.com]
|
6
|
+
* @param {Object} x The variable to debug
|
7
|
+
* @param {Number} max The maximum number of recursions allowed (keep low, around 5 for HTML elements to prevent errors) [default: 10]
|
8
|
+
* @param {String} sep The separator to use between [default: a single space ' ']
|
9
|
+
* @param {Number} l The current level deep (amount of recursion). Do not use this parameter: it's for the function's own use
|
10
|
+
*/
|
11
|
+
function print_r(x, max, sep, l) {
|
12
|
+
|
13
|
+
l = l || 0;
|
14
|
+
max = max || 10;
|
15
|
+
sep = sep || ' ';
|
16
|
+
|
17
|
+
if (l > max) {
|
18
|
+
throw("Too much recursion");
|
19
|
+
};
|
20
|
+
|
21
|
+
var r = '';
|
22
|
+
|
23
|
+
if (x === null) {
|
24
|
+
r += "null";
|
25
|
+
} else if (is_array(x)) {
|
26
|
+
r += '[' + x.map(function(i) {
|
27
|
+
return print_r(i, max, sep, (l + 1));
|
28
|
+
}).join(', ') + ']';
|
29
|
+
} else if(is_object(x)) {
|
30
|
+
r += '{'
|
31
|
+
var pairs = [];
|
32
|
+
for (i in x) {
|
33
|
+
pairs.push('"' + i + '": ' + print_r(x[i], max, sep, (l + 1)));
|
34
|
+
}
|
35
|
+
r += pairs.join(', ');
|
36
|
+
r += '}';
|
37
|
+
} else if(is_string(x)) {
|
38
|
+
r += '"' + x + "\"";
|
39
|
+
} else {
|
40
|
+
r += x;
|
41
|
+
};
|
42
|
+
|
43
|
+
return r;
|
44
|
+
|
45
|
+
function is_string(a) {
|
46
|
+
return typeof a === 'string';
|
47
|
+
};
|
48
|
+
|
49
|
+
function is_array(a) {
|
50
|
+
return (a &&
|
51
|
+
typeof a === 'object' &&
|
52
|
+
a.constructor === Array);
|
53
|
+
};
|
54
|
+
|
55
|
+
function is_object(a) {
|
56
|
+
return a && typeof a == 'object'
|
57
|
+
};
|
58
|
+
|
59
|
+
};
|
60
|
+
|
@@ -19,7 +19,11 @@ module CouchPotato
|
|
19
19
|
|
20
20
|
def process_results(results)
|
21
21
|
results['rows'].map do |row|
|
22
|
-
|
22
|
+
if row['doc'].instance_of?(klass)
|
23
|
+
row['doc']
|
24
|
+
else
|
25
|
+
klass.json_create row['doc'] || row['value'].merge(:_id => row['id'] || row['key'])
|
26
|
+
end
|
23
27
|
end
|
24
28
|
end
|
25
29
|
end
|
@@ -15,12 +15,16 @@ module CouchPotato
|
|
15
15
|
|
16
16
|
module ClassMethods
|
17
17
|
# Declare a CouchDB view, for examples on how to use see the *ViewSpec classes in CouchPotato::View
|
18
|
-
def views
|
19
|
-
|
18
|
+
def views(view_name = nil)
|
19
|
+
if view_name
|
20
|
+
_find_view(view_name)
|
21
|
+
else
|
22
|
+
@views ||= {}
|
23
|
+
end
|
20
24
|
end
|
21
25
|
|
22
26
|
def execute_view(view_name, view_parameters)
|
23
|
-
view_spec_class(views
|
27
|
+
view_spec_class(views(view_name)[:type]).new(self, view_name, views(view_name), view_parameters)
|
24
28
|
end
|
25
29
|
|
26
30
|
def view(view_name, options)
|
@@ -38,6 +42,11 @@ module CouchPotato
|
|
38
42
|
CouchPotato::View.const_get("#{name}ViewSpec")
|
39
43
|
end
|
40
44
|
end
|
45
|
+
|
46
|
+
def _find_view(view)
|
47
|
+
return @views[view] if @views && @views[view]
|
48
|
+
superclass._find_view(view) if superclass && superclass.respond_to?(:_find_view)
|
49
|
+
end
|
41
50
|
end
|
42
51
|
end
|
43
52
|
end
|
@@ -23,7 +23,7 @@ module CouchPotato
|
|
23
23
|
|
24
24
|
def create_view
|
25
25
|
design_doc = @database.get "_design/#{@design_document_name}" rescue nil
|
26
|
-
design_doc ||= {'views' => {}, "_id" => "_design/#{@design_document_name}"}
|
26
|
+
design_doc ||= {'views' => {}, "_id" => "_design/#{@design_document_name}", "language" => "javascript"}
|
27
27
|
design_doc['views'][@view_name.to_s] = {
|
28
28
|
'map' => @map_function,
|
29
29
|
'reduce' => @reduce_function
|
data/lib/couch_potato.rb
CHANGED
@@ -5,6 +5,7 @@ require 'json/add/rails'
|
|
5
5
|
|
6
6
|
require 'ostruct'
|
7
7
|
|
8
|
+
JSON.create_id = 'ruby_class'
|
8
9
|
|
9
10
|
module CouchPotato
|
10
11
|
Config = Struct.new(:database_name).new
|
@@ -23,7 +24,7 @@ module CouchPotato
|
|
23
24
|
|
24
25
|
def self.full_url_to_database
|
25
26
|
raise('No Database configured. Set CouchPotato::Config.database_name') unless CouchPotato::Config.database_name
|
26
|
-
if CouchPotato::Config.database_name
|
27
|
+
if CouchPotato::Config.database_name.match(%r{https?://})
|
27
28
|
CouchPotato::Config.database_name
|
28
29
|
else
|
29
30
|
"http://127.0.0.1:5984/#{CouchPotato::Config.database_name}"
|
data/spec/attachments_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe CouchPotato, 'attachments' do
|
|
13
13
|
comment._attachments = {'body' => {'data' => 'a useful comment', 'content_type' => 'text/plain'}}
|
14
14
|
CouchPotato.database.save! comment
|
15
15
|
comment_reloaded = CouchPotato.database.load comment.id
|
16
|
-
comment_reloaded._attachments
|
16
|
+
comment_reloaded._attachments["body"].should include({"content_type" => "text/plain", "stub" => true, "length" => 16})
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should have an empty array for a new object" do
|
data/spec/callbacks_spec.rb
CHANGED
@@ -268,4 +268,38 @@ describe "lambda callbacks" do
|
|
268
268
|
recorder.run_callbacks :before_create
|
269
269
|
recorder.lambda_works.should be_true
|
270
270
|
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "validation callbacks" do
|
274
|
+
class ValidatedUser
|
275
|
+
include CouchPotato::Persistence
|
276
|
+
|
277
|
+
property :name
|
278
|
+
before_validation :check_name
|
279
|
+
validates_presence_of :name
|
280
|
+
|
281
|
+
def check_name
|
282
|
+
errors.add(:name, 'should be Paul') unless name == "Paul"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should keep error messages set in custom before_validation filters" do
|
287
|
+
user = ValidatedUser.new(:name => "john")
|
288
|
+
user.valid?.should == false
|
289
|
+
user.errors.on(:name).should == "should be Paul"
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should combine the errors from validations and callbacks" do
|
293
|
+
user = ValidatedUser.new(:name => nil)
|
294
|
+
user.valid?.should == false
|
295
|
+
user.errors.on(:name).should == ["can't be empty", "should be Paul"]
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should clear the errors on subsequent calls to valid?" do
|
299
|
+
user = ValidatedUser.new(:name => nil)
|
300
|
+
user.valid?.should == false
|
301
|
+
user.name = 'Paul'
|
302
|
+
user.valid?.should == true
|
303
|
+
user.errors.on(:name).should == nil
|
304
|
+
end
|
271
305
|
end
|
data/spec/create_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe "create" do
|
|
8
8
|
it "should store the class" do
|
9
9
|
@comment = Comment.new :title => 'my_title'
|
10
10
|
CouchPotato.database.save_document! @comment
|
11
|
-
CouchPotato.couchrest_database.get(@comment.id)
|
11
|
+
CouchPotato.couchrest_database.get(@comment.id).ruby_class.should == 'Comment'
|
12
12
|
end
|
13
13
|
end
|
14
14
|
describe "fails" do
|
data/spec/custom_view_spec.rb
CHANGED
@@ -18,6 +18,9 @@ class Build
|
|
18
18
|
view :with_view_options, :group => true, :key => :time
|
19
19
|
end
|
20
20
|
|
21
|
+
class CustomBuild < Build
|
22
|
+
end
|
23
|
+
|
21
24
|
describe 'view' do
|
22
25
|
before(:each) do
|
23
26
|
recreate_db
|
@@ -108,6 +111,13 @@ describe 'view' do
|
|
108
111
|
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01'})
|
109
112
|
CouchPotato.database.view(Build.custom_timeline_returns_docs).map(&:state).should == ['success']
|
110
113
|
end
|
114
|
+
|
115
|
+
it "should still return instance of class if document included 'ruby_class'" do
|
116
|
+
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01', :ruby_class => "Build"})
|
117
|
+
view_data = CouchPotato.database.view(Build.custom_timeline_returns_docs)
|
118
|
+
view_data.map(&:class).should == [Build]
|
119
|
+
view_data.map(&:state).should == ['success']
|
120
|
+
end
|
111
121
|
end
|
112
122
|
|
113
123
|
describe "additional reduce function given" do
|
@@ -146,4 +156,11 @@ describe 'view' do
|
|
146
156
|
end
|
147
157
|
end
|
148
158
|
|
159
|
+
describe "inherited views" do
|
160
|
+
it "should support parent views for objects of the subclass" do
|
161
|
+
CouchPotato.database.save_document CustomBuild.new(:state => 'success', :time => '2008-01-01')
|
162
|
+
CouchPotato.database.view(CustomBuild.timeline).should have(1).item
|
163
|
+
CouchPotato.database.view(CustomBuild.timeline).first.should be_kind_of(CustomBuild)
|
164
|
+
end
|
165
|
+
end
|
149
166
|
end
|
data/spec/fixtures/person.rb
CHANGED
data/spec/property_spec.rb
CHANGED
@@ -18,6 +18,9 @@ class Watch
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
class CuckooClock < Watch
|
22
|
+
property :cuckoo
|
23
|
+
end
|
21
24
|
|
22
25
|
describe 'properties' do
|
23
26
|
before(:all) do
|
@@ -57,6 +60,45 @@ describe 'properties' do
|
|
57
60
|
c.title.should == {'key' => 'value'}
|
58
61
|
end
|
59
62
|
|
63
|
+
def it_should_persist value
|
64
|
+
c = Comment.new :title => value
|
65
|
+
CouchPotato.database.save_document! c
|
66
|
+
c = CouchPotato.database.load_document c.id
|
67
|
+
c.title.should == value
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should persist a child class" do
|
71
|
+
it_should_persist Child.new('text' => 'some text')
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should persist a hash with a child class" do
|
75
|
+
it_should_persist 'child' => Child.new('text' => 'some text')
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should persist an array with a child class" do
|
79
|
+
it_should_persist [Child.new('text' => 'some text')]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should persist something very complex" do
|
83
|
+
something_very_complex = [
|
84
|
+
[
|
85
|
+
[
|
86
|
+
{
|
87
|
+
'what' => [
|
88
|
+
{
|
89
|
+
'ever' => Child.new('text' => 'some text')
|
90
|
+
}
|
91
|
+
],
|
92
|
+
'number' => 3
|
93
|
+
},
|
94
|
+
"string"
|
95
|
+
],
|
96
|
+
Child.new('text' => 'nothing')
|
97
|
+
]
|
98
|
+
]
|
99
|
+
it_should_persist something_very_complex
|
100
|
+
end
|
101
|
+
|
60
102
|
it "should persist a Time object" do
|
61
103
|
w = Watch.new :time => Time.now
|
62
104
|
CouchPotato.database.save_document! w
|
@@ -98,4 +140,17 @@ describe 'properties' do
|
|
98
140
|
Comment.new(:title => '').title?.should be_false
|
99
141
|
end
|
100
142
|
end
|
143
|
+
|
144
|
+
describe "with subclasses" do
|
145
|
+
it "should include properties of superclasses" do
|
146
|
+
CuckooClock.properties.map(&:name).should include(:time)
|
147
|
+
CuckooClock.properties.map(&:name).should include(:cuckoo)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should return attributes of superclasses" do
|
151
|
+
clock = CuckooClock.new(:time => Time.now, :cuckoo => 'bavarian')
|
152
|
+
clock.attributes[:time].should_not == nil
|
153
|
+
clock.attributes[:cuckoo].should == 'bavarian'
|
154
|
+
end
|
155
|
+
end
|
101
156
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/unit/database_spec.rb
CHANGED
@@ -18,6 +18,32 @@ describe CouchPotato::Database, 'new' do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
describe CouchPotato::Database, 'full_url_to_database' do
|
22
|
+
before(:all) do
|
23
|
+
@database_url = CouchPotato::Config.database_name
|
24
|
+
end
|
25
|
+
|
26
|
+
after(:all) do
|
27
|
+
CouchPotato::Config.database_name = @database_url
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return the full URL when it starts with https" do
|
31
|
+
CouchPotato::Config.database_name = "https://example.com/database"
|
32
|
+
CouchPotato.full_url_to_database.should == 'https://example.com/database'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return the full URL when it starts with http" do
|
36
|
+
CouchPotato::Config.database_name = "http://example.com/database"
|
37
|
+
CouchPotato.full_url_to_database.should == 'http://example.com/database'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use localhost when no protocol was specified" do
|
41
|
+
CouchPotato::Config.database_name = "database"
|
42
|
+
CouchPotato.full_url_to_database.should == 'http://127.0.0.1:5984/database'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
21
47
|
describe CouchPotato::Database, 'load' do
|
22
48
|
it "should raise an exception if nil given" do
|
23
49
|
db = CouchPotato::Database.new(stub('couchrest db', :info => nil))
|
@@ -29,22 +55,153 @@ describe CouchPotato::Database, 'load' do
|
|
29
55
|
it "should set itself on the model" do
|
30
56
|
user = mock 'user'
|
31
57
|
DbTestUser.stub!(:new).and_return(user)
|
32
|
-
db = CouchPotato::Database.new(stub('couchrest db', :info => nil, :get => {'ruby_class' => 'DbTestUser'}))
|
58
|
+
db = CouchPotato::Database.new(stub('couchrest db', :info => nil, :get => DbTestUser.json_create({'ruby_class' => 'DbTestUser'})))
|
33
59
|
user.should_receive(:database=).with(db)
|
34
60
|
db.load '1'
|
35
61
|
end
|
36
62
|
|
37
63
|
it "should load namespaced models" do
|
38
|
-
db = CouchPotato::Database.new(stub('couchrest db', :info => nil, :get => {'ruby_class' => 'Parent::Child'}))
|
64
|
+
db = CouchPotato::Database.new(stub('couchrest db', :info => nil, :get => Parent::Child.json_create({'ruby_class' => 'Parent::Child'})))
|
39
65
|
db.load('1').class.should == Parent::Child
|
40
66
|
end
|
41
67
|
end
|
42
68
|
|
43
69
|
describe CouchPotato::Database, 'save_document' do
|
70
|
+
before(:each) do
|
71
|
+
@db = CouchPotato::Database.new(stub('couchrest db').as_null_object)
|
72
|
+
end
|
73
|
+
|
44
74
|
it "should set itself on the model for a new object before doing anything else" do
|
45
|
-
db
|
46
|
-
user = stub('user', :new? => true
|
47
|
-
user.should_receive(:database=).with(db)
|
48
|
-
db.save_document user
|
75
|
+
@db.stub(:valid_document?).and_return false
|
76
|
+
user = stub('user', :new? => true).as_null_object
|
77
|
+
user.should_receive(:database=).with(@db)
|
78
|
+
@db.save_document user
|
79
|
+
end
|
80
|
+
|
81
|
+
class Category
|
82
|
+
include CouchPotato::Persistence
|
83
|
+
property :name
|
84
|
+
validates_presence_of :name
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should return false when creating a new document and the validations failed" do
|
88
|
+
CouchPotato.database.save_document(Category.new).should == false
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return false when saving an existing document and the validations failed" do
|
92
|
+
category = Category.new(:name => "pizza")
|
93
|
+
CouchPotato.database.save_document(category).should == true
|
94
|
+
category.name = nil
|
95
|
+
CouchPotato.database.save_document(category).should == false
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "when creating with validate options" do
|
99
|
+
it "should not run the validations when saved with false" do
|
100
|
+
category = Category.new
|
101
|
+
@db.save_document(category, false)
|
102
|
+
category.new?.should == false
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should run the validations when saved with true" do
|
106
|
+
category = Category.new
|
107
|
+
@db.save_document(category, true)
|
108
|
+
category.new?.should == true
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should run the validations when saved with default" do
|
112
|
+
category = Category.new
|
113
|
+
@db.save_document(category)
|
114
|
+
category.new?.should == true
|
115
|
+
end
|
49
116
|
end
|
50
|
-
|
117
|
+
|
118
|
+
describe "when updating with validate options" do
|
119
|
+
it "should not run the validations when saved with false" do
|
120
|
+
category = Category.new(:name => 'food')
|
121
|
+
@db.save_document(category)
|
122
|
+
category.new?.should == false
|
123
|
+
category.name = nil
|
124
|
+
@db.save_document(category, false)
|
125
|
+
category.dirty?.should == false
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should run the validations when saved with true" do
|
129
|
+
category = Category.new(:name => "food")
|
130
|
+
@db.save_document(category)
|
131
|
+
category.new?.should == false
|
132
|
+
category.name = nil
|
133
|
+
@db.save_document(category, true)
|
134
|
+
category.dirty?.should == true
|
135
|
+
category.valid?.should == false
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should run the validations when saved with default" do
|
139
|
+
category = Category.new(:name => "food")
|
140
|
+
@db.save_document(category)
|
141
|
+
category.new?.should == false
|
142
|
+
category.name = nil
|
143
|
+
@db.save_document(category)
|
144
|
+
category.dirty?.should == true
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "when saving documents with errors set in callbacks" do
|
149
|
+
class Vulcan
|
150
|
+
include CouchPotato::Persistence
|
151
|
+
before_validation_on_create :set_errors
|
152
|
+
before_validation_on_update :set_errors
|
153
|
+
|
154
|
+
property :name
|
155
|
+
validates_presence_of :name
|
156
|
+
|
157
|
+
def set_errors
|
158
|
+
errors.add(:validation, "failed")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
|
163
|
+
spock = Vulcan.new(:name => 'spock')
|
164
|
+
@db.save_document(spock)
|
165
|
+
spock.errors.on(:validation).should == 'failed'
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
|
169
|
+
spock = Vulcan.new(:name => 'spock')
|
170
|
+
@db.save_document(spock, false)
|
171
|
+
spock.new_record?.should == false
|
172
|
+
spock.name = "spock's father"
|
173
|
+
@db.save_document(spock)
|
174
|
+
spock.errors.on(:validation).should == 'failed'
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should keep errors generated from normal validations together with errors set in normal validations" do
|
178
|
+
spock = Vulcan.new
|
179
|
+
@db.save_document(spock)
|
180
|
+
spock.errors.on(:validation).should == 'failed'
|
181
|
+
spock.errors.on(:name).should == "can't be empty"
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should clear errors on subsequent, valid saves when creating" do
|
185
|
+
spock = Vulcan.new
|
186
|
+
@db.save_document(spock)
|
187
|
+
|
188
|
+
spock.name = 'Spock'
|
189
|
+
@db.save_document(spock)
|
190
|
+
spock.errors.on(:name).should == nil
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should clear errors on subsequent, valid saves when updating" do
|
194
|
+
spock = Vulcan.new(:name => 'spock')
|
195
|
+
@db.save_document(spock, false)
|
196
|
+
|
197
|
+
spock.name = nil
|
198
|
+
@db.save_document(spock)
|
199
|
+
spock.errors.on(:name).should == "can't be empty"
|
200
|
+
|
201
|
+
spock.name = 'Spock'
|
202
|
+
@db.save_document(spock)
|
203
|
+
spock.errors.on(:name).should == nil
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
@@ -86,7 +86,7 @@ describe 'dirty attribute tracking' do
|
|
86
86
|
|
87
87
|
describe "object loaded from database" do
|
88
88
|
before(:each) do
|
89
|
-
couchrest_db = stub('database', :get => {'_id' => '1', '_rev' => '2', 'food' => 'sushi', 'ruby_class' => 'Plate'}, :info => nil)
|
89
|
+
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', 'ruby_class' => 'Plate'}), :info => nil)
|
90
90
|
@plate = CouchPotato::Database.new(couchrest_db).load_document '1'
|
91
91
|
end
|
92
92
|
|
@@ -104,7 +104,7 @@ describe 'dirty attribute tracking' do
|
|
104
104
|
end
|
105
105
|
|
106
106
|
it "should return true if array attribute changed" do
|
107
|
-
couchrest_db = stub('database', :get => {'_id' => '1', '_rev' => '2', 'food' => ['sushi'], 'ruby_class' => 'Plate'}, :info => nil)
|
107
|
+
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => ['sushi'], 'ruby_class' => 'Plate'}), :info => nil)
|
108
108
|
plate = CouchPotato::Database.new(couchrest_db).load_document '1'
|
109
109
|
plate.food << 'burger'
|
110
110
|
plate.should be_food_changed
|
@@ -119,7 +119,7 @@ describe 'dirty attribute tracking' do
|
|
119
119
|
|
120
120
|
describe "after save" do
|
121
121
|
it "should reset all attributes to not dirty" do
|
122
|
-
couchrest_db = stub('database', :get => {'_id' => '1', '_rev' => '2', 'food' => 'sushi', 'ruby_class' => 'Plate'}, :info => nil, :save_doc => {})
|
122
|
+
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', 'ruby_class' => 'Plate'}), :info => nil, :save_doc => {})
|
123
123
|
db = CouchPotato::Database.new(couchrest_db)
|
124
124
|
@plate = db.load_document '1'
|
125
125
|
@plate.food = 'burger'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
class Drink
|
4
|
+
include CouchPotato::Persistence
|
5
|
+
|
6
|
+
property :alcohol
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "json module" do
|
10
|
+
it "should inject JSON.create_id into hash representation of a persistence object" do
|
11
|
+
sake = Drink.new(:alcohol => "18%")
|
12
|
+
sake.to_hash[JSON.create_id].should eql("Drink")
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'couch_potato/rspec/matchers'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
describe CouchPotato::RSpec::MapToMatcher do
|
6
|
+
|
7
|
+
describe "basic map function" do
|
8
|
+
before(:each) do
|
9
|
+
@view_spec = OpenStruct.new(:map_function => "function(doc) {emit(doc.name, doc.tags.length);}")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should pass if the given function emits the expected javascript" do
|
13
|
+
@view_spec.should map({:name => 'horst', :tags => ['person', 'male']}).to([['horst', 2]])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should not pass if the given function emits different javascript" do
|
17
|
+
@view_spec.should_not map({:name => 'horst', :tags => ['person', 'male']}).to([['horst', 3]])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "functions emitting multiple times" do
|
22
|
+
before(:each) do
|
23
|
+
@view_spec = OpenStruct.new(:map_function => "function(doc) {emit(doc.name, doc.tags.length); emit(doc.tags[0], doc.tags[1])};")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should pass if the given function emits the expected javascript" do
|
27
|
+
@view_spec.should map({:name => 'horst', :tags => ['person', 'male']}).to([['horst', 2], ['person', 'male']])
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return false if the given function emits different javascript" do
|
31
|
+
@view_spec.should_not map({:name => 'horst', :tags => ['person', 'male']}).to([['horst', 2], ['male', 'person']])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "failing specs" do
|
36
|
+
before(:each) do
|
37
|
+
@view_spec = OpenStruct.new(:map_function => "function(doc) {emit(doc.name, null)}")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should have a nice error message for failing should" do
|
41
|
+
lambda {
|
42
|
+
@view_spec.should map({:name => 'bill'}).to([['linus', nil]])
|
43
|
+
}.should raise_error('Expected to map to [["linus", nil]] but got [["bill", nil]].')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should have a nice error message for failing should not" do
|
47
|
+
lambda {
|
48
|
+
@view_spec.should_not map({:name => 'bill'}).to([['bill', nil]])
|
49
|
+
}.should raise_error('Expected not to map to [["bill", nil]] but did.')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe CouchPotato::RSpec::ReduceToMatcher do
|
55
|
+
before(:each) do
|
56
|
+
@view_spec = OpenStruct.new(:reduce_function => "function(docs, keys, rereduce) {
|
57
|
+
if(rereduce) {
|
58
|
+
return(sum(keys) * 2);
|
59
|
+
} else {
|
60
|
+
return(sum(keys));
|
61
|
+
};
|
62
|
+
}")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should pass if the given function return the expected javascript" do
|
66
|
+
@view_spec.should reduce([], [1, 2, 3]).to(6)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not pass if the given function returns different javascript" do
|
70
|
+
@view_spec.should_not reduce([], [1, 2, 3]).to(7)
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "rereduce" do
|
74
|
+
it "should pass if the given function return the expected javascript" do
|
75
|
+
@view_spec.should rereduce([], [1, 2, 3]).to(12)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should not pass if the given function returns different javascript" do
|
79
|
+
@view_spec.should_not rereduce([], [1, 2, 3]).to(13)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'failing specs' do
|
84
|
+
|
85
|
+
it "should have a nice error message for failing should" do
|
86
|
+
lambda {
|
87
|
+
@view_spec.should reduce([], [1, 2, 3]).to(7)
|
88
|
+
}.should raise_error('Expected to reduce to 7 but got 6.')
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should have a nice error message for failing should not" do
|
92
|
+
lambda {
|
93
|
+
@view_spec.should_not reduce([], [1, 2, 3]).to(6)
|
94
|
+
}.should raise_error('Expected not to reduce to 6 but did.')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/spec/update_spec.rb
CHANGED
@@ -35,6 +35,6 @@ describe "create" do
|
|
35
35
|
it "should update the attributes" do
|
36
36
|
@comment.title = 'new title'
|
37
37
|
CouchPotato.database.save_document! @comment
|
38
|
-
CouchPotato.couchrest_database.get("#{@comment.id}")
|
38
|
+
CouchPotato.couchrest_database.get("#{@comment.id}").title.should == 'new title'
|
39
39
|
end
|
40
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couch_potato
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Lang
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-30 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -73,6 +73,10 @@ files:
|
|
73
73
|
- lib/couch_potato/persistence/properties.rb
|
74
74
|
- lib/couch_potato/persistence/simple_property.rb
|
75
75
|
- lib/couch_potato/persistence/validation.rb
|
76
|
+
- lib/couch_potato/rspec/matchers.rb
|
77
|
+
- lib/couch_potato/rspec/matchers/map_to_matcher.rb
|
78
|
+
- lib/couch_potato/rspec/matchers/print_r.js
|
79
|
+
- lib/couch_potato/rspec/matchers/reduce_to_matcher.rb
|
76
80
|
- lib/couch_potato/view/base_view_spec.rb
|
77
81
|
- lib/couch_potato/view/custom_view_spec.rb
|
78
82
|
- lib/couch_potato/view/custom_views.rb
|
@@ -99,6 +103,8 @@ files:
|
|
99
103
|
- spec/unit/customs_views_spec.rb
|
100
104
|
- spec/unit/database_spec.rb
|
101
105
|
- spec/unit/dirty_attributes_spec.rb
|
106
|
+
- spec/unit/json_create_id_spec.rb
|
107
|
+
- spec/unit/rspec_matchers_spec.rb
|
102
108
|
- spec/unit/string_spec.rb
|
103
109
|
- spec/unit/view_query_spec.rb
|
104
110
|
- spec/update_spec.rb
|
@@ -148,6 +154,8 @@ test_files:
|
|
148
154
|
- spec/unit/customs_views_spec.rb
|
149
155
|
- spec/unit/database_spec.rb
|
150
156
|
- spec/unit/dirty_attributes_spec.rb
|
157
|
+
- spec/unit/json_create_id_spec.rb
|
158
|
+
- spec/unit/rspec_matchers_spec.rb
|
151
159
|
- spec/unit/string_spec.rb
|
152
160
|
- spec/unit/view_query_spec.rb
|
153
161
|
- spec/update_spec.rb
|