couch_potato 1.1.1 → 1.1.2
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.
- checksums.yaml +7 -0
- data/.travis.yml +2 -1
- data/CHANGES.md +8 -0
- data/README.md +11 -1
- data/lib/couch_potato.rb +20 -7
- data/lib/couch_potato/persistence.rb +6 -0
- data/lib/couch_potato/persistence/type_caster.rb +1 -1
- data/lib/couch_potato/rspec/matchers/map_reduce_to_matcher.rb +3 -0
- data/lib/couch_potato/version.rb +1 -1
- data/lib/couch_potato/view/custom_view_spec.rb +1 -1
- data/spec/property_spec.rb +15 -0
- data/spec/unit/couch_potato_spec.rb +20 -5
- data/spec/unit/rspec_matchers_spec.rb +7 -0
- data/spec/views_spec.rb +10 -0
- metadata +23 -39
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 25d897ae6682560bf5d76b11e037d2aab1cb67ed
|
4
|
+
data.tar.gz: 22d1dc7f80cf657bfa12957dd0ac7454b4a09bbe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eb2dc8906dc29cdbd33137bbe94f2336757ab79d38d6082671b4f4d0f5292cfd583c0e4eafcb0dff5ffe79b9d01897f253aa9d1f8c6a4db11d1099b8e0b4c2dc
|
7
|
+
data.tar.gz: 0598953fcca4915c144ff632cb9d41630dd3493cb42bace24f7550f12f14221baeb159510a7338e51747a87cca02ce5be89cbbc60d13b5944575af8859d6f06d
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## Changes
|
2
2
|
|
3
|
+
### 1.1.2
|
4
|
+
|
5
|
+
* fixes `CouchPotato.models` did not include subclasses
|
6
|
+
* adds `CouchPotato.use` (Daniel Lohse)
|
7
|
+
* fixes MapReduceToMatcher when reduce uses `sum` (Daniel Lohse)
|
8
|
+
* adds `CouchPotato::Config.database_host` for using multiple databases in a project (Daniel Lohse)
|
9
|
+
* makes `cast_native` cast floats with no leading digits (wrshawn)
|
10
|
+
|
3
11
|
### 1.1.1
|
4
12
|
|
5
13
|
* fixes properties were leaked to sibling classes (Alexander Lang)
|
data/README.md
CHANGED
@@ -27,7 +27,7 @@ Lastly Couch Potato aims to provide a seamless integration with Ruby on Rails, e
|
|
27
27
|
|
28
28
|
### Supported Environments
|
29
29
|
|
30
|
-
* Ruby 1.9.3, 2.0, Rubinius
|
30
|
+
* Ruby 1.9.3, 2.0, 2.1, Rubinius
|
31
31
|
* CouchDB 1.2.0
|
32
32
|
* ActiveSupport 3.2, 4.0
|
33
33
|
|
@@ -52,6 +52,11 @@ The server URL will default to http://localhost:5984/ unless specified:
|
|
52
52
|
|
53
53
|
CouchPotato::Config.database_name = "http://example.com:5984/name_of_the_db"
|
54
54
|
|
55
|
+
But you can also specify the database host separately from the database name:
|
56
|
+
|
57
|
+
CouchPotato::Config.database_host = "http://example.com:5984"
|
58
|
+
CouchPotato::Config.database_name = "name_of_the_db"
|
59
|
+
|
55
60
|
Or with authentication
|
56
61
|
|
57
62
|
CouchPotato::Config.database_name = "http://username:password@example.com:5984/name_of_the_db"
|
@@ -414,6 +419,11 @@ Couch Potato supports accessing multiple CouchDBs:
|
|
414
419
|
|
415
420
|
Unless configured otherwise this would save the customer model to _http://127.0.0.1:5984/couch_customer_.
|
416
421
|
|
422
|
+
You can also first retrieve the database instance:
|
423
|
+
|
424
|
+
db = CouchPotato.use('couch_customer')
|
425
|
+
db.save @customer
|
426
|
+
|
417
427
|
#### Testing
|
418
428
|
|
419
429
|
To make testing easier and faster database logic has been put into its own class, which you can replace and stub out in whatever way you want:
|
data/lib/couch_potato.rb
CHANGED
@@ -8,14 +8,15 @@ JSON.create_id = 'ruby_class'
|
|
8
8
|
CouchRest.decode_json_objects = true
|
9
9
|
|
10
10
|
module CouchPotato
|
11
|
-
Config = Struct.new(:database_name, :split_design_documents_per_view, :default_language).new
|
11
|
+
Config = Struct.new(:database_host, :database_name, :split_design_documents_per_view, :default_language).new
|
12
12
|
Config.split_design_documents_per_view = false
|
13
13
|
Config.default_language = :javascript
|
14
|
+
Config.database_host = "http://127.0.0.1:5984"
|
14
15
|
|
15
16
|
class NotFound < StandardError; end
|
16
17
|
class Conflict < StandardError; end
|
17
18
|
|
18
|
-
# returns all the classes that
|
19
|
+
# returns all the classes that include the CouchPotato::Persistence module
|
19
20
|
def self.models
|
20
21
|
@models ||= []
|
21
22
|
@models
|
@@ -28,7 +29,14 @@ module CouchPotato
|
|
28
29
|
|
29
30
|
# Returns the underlying CouchRest database object if you want low level access to your CouchDB. You have to set the CouchPotato::Config.database_name before this works.
|
30
31
|
def self.couchrest_database
|
31
|
-
@@__couchrest_database ||= CouchRest.database(full_url_to_database)
|
32
|
+
@@__couchrest_database ||= CouchRest.database(full_url_to_database(CouchPotato::Config.database_name, CouchPotato::Config.database_host))
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a specific database instance
|
36
|
+
def self.use(database_name)
|
37
|
+
@@__databases ||= {}
|
38
|
+
@@__databases["#{database_name}"] = Database.new(couchrest_database_for_name!(database_name)) unless @@__databases["#{database_name}"]
|
39
|
+
@@__databases["#{database_name}"]
|
32
40
|
end
|
33
41
|
|
34
42
|
# Executes a block of code and yields a datbase with the given name.
|
@@ -44,19 +52,24 @@ module CouchPotato
|
|
44
52
|
yield(@@__databases["#{database_name}"])
|
45
53
|
end
|
46
54
|
|
47
|
-
#
|
55
|
+
# Returns a CouchRest-Database for directly accessing that functionality.
|
48
56
|
def self.couchrest_database_for_name(database_name)
|
49
|
-
CouchRest.database(full_url_to_database(database_name))
|
57
|
+
CouchRest.database(full_url_to_database(database_name, CouchPotato::Config.database_host))
|
58
|
+
end
|
59
|
+
|
60
|
+
# Creates a CouchRest-Database for directly accessing that functionality.
|
61
|
+
def self.couchrest_database_for_name!(database_name)
|
62
|
+
CouchRest.database!(full_url_to_database(database_name))
|
50
63
|
end
|
51
64
|
|
52
65
|
private
|
53
66
|
|
54
|
-
def self.full_url_to_database(database_name=CouchPotato::Config.database_name)
|
67
|
+
def self.full_url_to_database(database_name=CouchPotato::Config.database_name, database_host = CouchPotato::Config.database_host)
|
55
68
|
raise('No Database configured. Set CouchPotato::Config.database_name') unless database_name
|
56
69
|
if database_name.match(%r{https?://})
|
57
70
|
database_name
|
58
71
|
else
|
59
|
-
"
|
72
|
+
"#{database_host}/#{database_name}"
|
60
73
|
end
|
61
74
|
end
|
62
75
|
end
|
@@ -27,11 +27,17 @@ module CouchPotato
|
|
27
27
|
attr_accessor :_id, :_rev, :_deleted, :database
|
28
28
|
alias_method :id, :_id
|
29
29
|
alias_method :id=, :_id=
|
30
|
+
|
31
|
+
def self.inherited(child)
|
32
|
+
super
|
33
|
+
CouchPotato.models << child
|
34
|
+
end
|
30
35
|
end
|
31
36
|
|
32
37
|
CouchPotato.models << base
|
33
38
|
end
|
34
39
|
|
40
|
+
|
35
41
|
# initialize a new instance of the model optionally passing it a hash of attributes.
|
36
42
|
# the attributes have to be declared using the #property method.
|
37
43
|
# the new model will be yielded to an optionally given block.
|
@@ -50,6 +50,9 @@ module CouchPotato
|
|
50
50
|
var emit = function(key, value) {
|
51
51
|
mapResults.push({key: key, value: value});
|
52
52
|
};
|
53
|
+
var sum = function(values) {
|
54
|
+
return values.reduce(function(memo, value) { return memo + value; });
|
55
|
+
};
|
53
56
|
for (var i in docs) {
|
54
57
|
map(docs[i]);
|
55
58
|
}
|
data/lib/couch_potato/version.rb
CHANGED
@@ -26,7 +26,7 @@ module CouchPotato
|
|
26
26
|
results['rows'].first.try(:[], 'value') || 0
|
27
27
|
else
|
28
28
|
results['rows'].map do |row|
|
29
|
-
if row['doc'].
|
29
|
+
if row['doc'].kind_of?(klass)
|
30
30
|
row['doc']
|
31
31
|
else
|
32
32
|
result = row['doc'] || (row['value'].merge(:_id => row['id'] || row['key']) unless view_parameters[:include_docs])
|
data/spec/property_spec.rb
CHANGED
@@ -12,6 +12,7 @@ class Watch
|
|
12
12
|
property :custom_address, :type => [Address]
|
13
13
|
property :overwritten_read
|
14
14
|
property :overwritten_write
|
15
|
+
property :diameter, :type => Float
|
15
16
|
|
16
17
|
def overwritten_read
|
17
18
|
super.to_s
|
@@ -73,6 +74,20 @@ describe 'properties' do
|
|
73
74
|
c.title.should == 3
|
74
75
|
end
|
75
76
|
|
77
|
+
it "should persist a float with leading digits" do
|
78
|
+
w = Watch.new :diameter => "46.5"
|
79
|
+
CouchPotato.database.save_document! w
|
80
|
+
w = CouchPotato.database.load_document w.id
|
81
|
+
w.diameter.should == 46.5
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should persist a float with no leading digits" do
|
85
|
+
w = Watch.new :diameter => ".465"
|
86
|
+
CouchPotato.database.save_document! w
|
87
|
+
w = CouchPotato.database.load_document w.id
|
88
|
+
w.diameter.should == 0.465
|
89
|
+
end
|
90
|
+
|
76
91
|
it "should persist a big decimal" do
|
77
92
|
require 'bigdecimal'
|
78
93
|
c = BigDecimalContainer.new :number => BigDecimal.new( '42.42' )
|
@@ -7,23 +7,38 @@ describe CouchPotato, 'full_url_to_database' do
|
|
7
7
|
after(:each) do
|
8
8
|
CouchPotato::Config.database_name = @original_database_name
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
it "should add the default localhost and port if only a name is set" do
|
12
12
|
CouchPotato::Config.database_name = 'test'
|
13
13
|
CouchPotato.full_url_to_database.should == 'http://127.0.0.1:5984/test'
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
it "should return the set url" do
|
17
17
|
CouchPotato::Config.database_name = 'http://db.local/test'
|
18
18
|
CouchPotato.full_url_to_database.should == 'http://db.local/test'
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
describe CouchPotato, 'use' do
|
23
|
+
it 'should return the db object' do
|
24
|
+
db = CouchPotato.use("testdb")
|
25
|
+
db.couchrest_database.root.should == 'http://127.0.0.1:5984/testdb'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
22
29
|
describe CouchPotato, '.models' do
|
23
30
|
it "returns all classes that have implemented CouchPotato::Persistence" do
|
24
31
|
clazz = Class.new
|
25
32
|
clazz.send(:include, CouchPotato::Persistence)
|
26
|
-
|
27
|
-
CouchPotato.models.
|
33
|
+
|
34
|
+
expect(CouchPotato.models).to include(clazz)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns all subclasses of classes that have implemented CouchPotato::Persistence' do
|
38
|
+
clazz = Class.new
|
39
|
+
clazz.send(:include, CouchPotato::Persistence)
|
40
|
+
subclazz = Class.new clazz
|
41
|
+
|
42
|
+
expect(CouchPotato.models).to include(subclazz)
|
28
43
|
end
|
29
|
-
end
|
44
|
+
end
|
@@ -145,6 +145,13 @@ describe CouchPotato::RSpec::MapReduceToMatcher do
|
|
145
145
|
spec.should map_reduce({}).to({"key" => nil, "value" => "test"})
|
146
146
|
end
|
147
147
|
|
148
|
+
it "should handle sum function" do
|
149
|
+
spec = stub(
|
150
|
+
:map_function => "function(doc) { emit(null, doc.age); }",
|
151
|
+
:reduce_function => "function(keys, values) { return sum(values); }")
|
152
|
+
spec.should map_reduce(@docs).to({"key" => nil, "value" => 103})
|
153
|
+
end
|
154
|
+
|
148
155
|
context "without grouping" do
|
149
156
|
it "should not group by key by default" do
|
150
157
|
@view_spec.should map_reduce(@docs).to({"key" => nil, "value" => 8})
|
data/spec/views_spec.rb
CHANGED
@@ -5,6 +5,7 @@ class Build
|
|
5
5
|
|
6
6
|
property :state
|
7
7
|
property :time
|
8
|
+
property :type, :type => String, :default => 'Build'
|
8
9
|
|
9
10
|
view :timeline, :key => :time
|
10
11
|
view :count, :key => :time, :reduce => true
|
@@ -17,9 +18,11 @@ class Build
|
|
17
18
|
view :raw, :type => :raw, :map => "function(doc) {emit(doc._id, doc.state)}"
|
18
19
|
view :filtered_raw, :type => :raw, :map => "function(doc) {emit(doc._id, doc.state)}", :results_filter => lambda{|res| res['rows'].map{|row| row['value']}}
|
19
20
|
view :with_view_options, :group => true, :key => :time
|
21
|
+
view :all, :map => "function(doc) { if (doc && doc.type == 'Build') emit(doc._id, 1); }", :include_docs => true, :type => :custom
|
20
22
|
end
|
21
23
|
|
22
24
|
class CustomBuild < Build
|
25
|
+
property :server
|
23
26
|
end
|
24
27
|
|
25
28
|
class ErlangBuild
|
@@ -239,6 +242,13 @@ describe 'views' do
|
|
239
242
|
@db.view(CustomBuild.timeline).size.should == 1
|
240
243
|
@db.view(CustomBuild.timeline).first.should be_kind_of(CustomBuild)
|
241
244
|
end
|
245
|
+
|
246
|
+
it "should return instances of subclasses as well if a special view exists" do
|
247
|
+
@db.save_document Build.new(:state => 'success', :time => '2008-01-01')
|
248
|
+
@db.save_document CustomBuild.new(:state => 'success', :time => '2008-01-01', :server => 'Jenkins')
|
249
|
+
results = @db.view(Build.all)
|
250
|
+
results.map(&:class).should == [CustomBuild, Build]
|
251
|
+
end
|
242
252
|
end
|
243
253
|
|
244
254
|
describe "list functions" do
|
metadata
CHANGED
@@ -1,126 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couch_potato
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Alexander Lang
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-03-05 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: json
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '1.6'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '1.6'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: couchrest
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- - ~>
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: 1.2.0
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- - ~>
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: 1.2.0
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: activemodel
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: rspec
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- - ~>
|
59
|
+
- - "~>"
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: 2.11.0
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- - ~>
|
66
|
+
- - "~>"
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: 2.11.0
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: timecop
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - ">="
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: tzinfo
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - ">="
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - ">="
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: rake
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
|
-
- -
|
101
|
+
- - ">="
|
116
102
|
- !ruby/object:Gem::Version
|
117
103
|
version: '0'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
|
-
- -
|
108
|
+
- - ">="
|
124
109
|
- !ruby/object:Gem::Version
|
125
110
|
version: '0'
|
126
111
|
description: Ruby persistence layer for CouchDB
|
@@ -129,8 +114,8 @@ executables: []
|
|
129
114
|
extensions: []
|
130
115
|
extra_rdoc_files: []
|
131
116
|
files:
|
132
|
-
- .gitignore
|
133
|
-
- .travis.yml
|
117
|
+
- ".gitignore"
|
118
|
+
- ".travis.yml"
|
134
119
|
- CHANGES.md
|
135
120
|
- CREDITS
|
136
121
|
- Gemfile
|
@@ -220,27 +205,26 @@ files:
|
|
220
205
|
- spec/views_spec.rb
|
221
206
|
homepage: http://github.com/langalex/couch_potato
|
222
207
|
licenses: []
|
208
|
+
metadata: {}
|
223
209
|
post_install_message:
|
224
210
|
rdoc_options: []
|
225
211
|
require_paths:
|
226
212
|
- lib
|
227
213
|
required_ruby_version: !ruby/object:Gem::Requirement
|
228
|
-
none: false
|
229
214
|
requirements:
|
230
|
-
- -
|
215
|
+
- - ">="
|
231
216
|
- !ruby/object:Gem::Version
|
232
217
|
version: '0'
|
233
218
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
234
|
-
none: false
|
235
219
|
requirements:
|
236
|
-
- -
|
220
|
+
- - ">="
|
237
221
|
- !ruby/object:Gem::Version
|
238
222
|
version: '0'
|
239
223
|
requirements: []
|
240
224
|
rubyforge_project:
|
241
|
-
rubygems_version:
|
225
|
+
rubygems_version: 2.2.0
|
242
226
|
signing_key:
|
243
|
-
specification_version:
|
227
|
+
specification_version: 4
|
244
228
|
summary: Ruby persistence layer for CouchDB
|
245
229
|
test_files:
|
246
230
|
- spec/attachments_spec.rb
|