couch_potato 0.5.1 → 0.5.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.
data/README.md CHANGED
@@ -256,6 +256,9 @@ If you have larger structures and you only want to load some attributes you can
256
256
 
257
257
  CouchPotato.database.view(User.everyone).first.name # => "joe"
258
258
  CouchPotato.database.view(User.everyone).first.bio # => nil
259
+
260
+ CouchPotato.database.first(User.everyone).name # => "joe" # convenience function, returns nil if nothing found
261
+ CouchPotato.database.first!(User.everyone) # would raise CouchPotato::NotFound if nothing was found
259
262
 
260
263
  You can also pass in custom map/reduce functions with the custom view spec:
261
264
 
@@ -4,7 +4,7 @@ module CouchPotato
4
4
  class ValidationsFailedError < ::StandardError; end
5
5
 
6
6
  def initialize(couchrest_database)
7
- @database = couchrest_database
7
+ @couchrest_database = couchrest_database
8
8
  begin
9
9
  couchrest_database.info
10
10
  rescue RestClient::ResourceNotFound
@@ -45,7 +45,7 @@ module CouchPotato
45
45
  # db.view(User.all(keys: [1, 2, 3]))
46
46
  def view(spec)
47
47
  results = CouchPotato::View::ViewQuery.new(
48
- database,
48
+ couchrest_database,
49
49
  spec.design_document,
50
50
  {spec.view_name => {
51
51
  :map => spec.map_function,
@@ -60,6 +60,16 @@ module CouchPotato
60
60
  end if processed_results.respond_to?(:each)
61
61
  processed_results
62
62
  end
63
+
64
+ # returns the first result from a #view query or nil
65
+ def first(spec)
66
+ view(spec).first
67
+ end
68
+
69
+ # returns th first result from a #view or raises CouchPotato::NotFound
70
+ def first!(spec)
71
+ first(spec) || raise(CouchPotato::NotFound)
72
+ end
63
73
 
64
74
  # saves a document. returns true on success, false on failure
65
75
  def save_document(document, validate = true)
@@ -81,7 +91,7 @@ module CouchPotato
81
91
  def destroy_document(document)
82
92
  document.run_callbacks :destroy do
83
93
  document._deleted = true
84
- database.delete_doc document.to_hash
94
+ couchrest_database.delete_doc document.to_hash
85
95
  end
86
96
  document._id = nil
87
97
  document._rev = nil
@@ -92,7 +102,7 @@ module CouchPotato
92
102
  def load_document(id)
93
103
  raise "Can't load a document without an id (got nil)" if id.nil?
94
104
  begin
95
- instance = database.get(id)
105
+ instance = couchrest_database.get(id)
96
106
  instance.database = self
97
107
  instance
98
108
  rescue(RestClient::ResourceNotFound)
@@ -102,7 +112,12 @@ module CouchPotato
102
112
  alias_method :load, :load_document
103
113
 
104
114
  def inspect #:nodoc:
105
- "#<CouchPotato::Database @root=\"#{database.root}\">"
115
+ "#<CouchPotato::Database @root=\"#{couchrest_database.root}\">"
116
+ end
117
+
118
+ # returns the underlying CouchRest::Database instance
119
+ def couchrest_database
120
+ @couchrest_database
106
121
  end
107
122
 
108
123
  private
@@ -121,7 +136,7 @@ module CouchPotato
121
136
 
122
137
  document.run_callbacks :save do
123
138
  document.run_callbacks :create do
124
- res = database.save_doc document.to_hash
139
+ res = couchrest_database.save_doc document.to_hash
125
140
  document._rev = res['rev']
126
141
  document._id = res['id']
127
142
  end
@@ -141,7 +156,7 @@ module CouchPotato
141
156
 
142
157
  document.run_callbacks :save do
143
158
  document.run_callbacks :update do
144
- res = database.save_doc document.to_hash
159
+ res = couchrest_database.save_doc document.to_hash
145
160
  document._rev = res['rev']
146
161
  end
147
162
  end
@@ -156,10 +171,5 @@ module CouchPotato
156
171
  end
157
172
  document.errors.empty?
158
173
  end
159
-
160
- def database
161
- @database
162
- end
163
-
164
174
  end
165
175
  end
@@ -13,7 +13,7 @@ module CouchPotato
13
13
  end
14
14
 
15
15
  def to_hash
16
- if _attachments
16
+ if _attachments && _attachments.any?
17
17
  super.merge('_attachments' => _attachments)
18
18
  else
19
19
  super
@@ -1,3 +1,3 @@
1
1
  module CouchPotato
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.2"
3
3
  end
@@ -41,7 +41,11 @@ module CouchPotato
41
41
  end
42
42
 
43
43
  def view_functions
44
- {'map' => @map_function, 'reduce' => @reduce_function}
44
+ if @reduce_function
45
+ {'map' => @map_function, 'reduce' => @reduce_function}
46
+ else
47
+ {'map' => @map_function}
48
+ end
45
49
  end
46
50
 
47
51
  def empty_design_document
data/lib/couch_potato.rb CHANGED
@@ -10,6 +10,8 @@ JSON.create_id = 'ruby_class'
10
10
  module CouchPotato
11
11
  Config = Struct.new(:database_name, :validation_framework).new
12
12
  Config.validation_framework = :active_model
13
+
14
+ class NotFound < StandardError; end
13
15
 
14
16
  # Returns a database instance which you can then use to create objects and query views. You have to set the CouchPotato::Config.database_name before this works.
15
17
  def self.database
@@ -124,7 +124,7 @@ describe 'properties' do
124
124
  db.should_receive(:save_doc).with do |attributes|
125
125
  attributes.has_key?(:ship_address).should == true
126
126
  end.and_return({})
127
- CouchPotato.database.stub(:database).and_return(db)
127
+ CouchPotato.database.stub(:couchrest_database).and_return(db)
128
128
  CouchPotato.database.save_document! p
129
129
  end
130
130
 
@@ -207,6 +207,46 @@ describe CouchPotato::Database, 'save_document' do
207
207
  end
208
208
  end
209
209
 
210
+ describe CouchPotato::Database, 'first' do
211
+ before(:each) do
212
+ @couchrest_db = stub('couchrest db').as_null_object
213
+ @db = CouchPotato::Database.new(@couchrest_db)
214
+ @result = stub('result')
215
+ @spec = stub('view spec', :process_results => [@result]).as_null_object
216
+ CouchPotato::View::ViewQuery.stub(:new => stub('view query', :query_view! => {'rows' => [@result]}))
217
+ end
218
+
219
+ it "should return the first result from a view query" do
220
+ @db.first(@spec).should == @result
221
+ end
222
+
223
+ it "should return nil if there are no results" do
224
+ @spec.stub(:process_results => [])
225
+ @db.first(@spec).should be_nil
226
+ end
227
+ end
228
+
229
+ describe CouchPotato::Database, 'first!' do
230
+ before(:each) do
231
+ @couchrest_db = stub('couchrest db').as_null_object
232
+ @db = CouchPotato::Database.new(@couchrest_db)
233
+ @result = stub('result')
234
+ @spec = stub('view spec', :process_results => [@result]).as_null_object
235
+ CouchPotato::View::ViewQuery.stub(:new => stub('view query', :query_view! => {'rows' => [@result]}))
236
+ end
237
+
238
+ it "should return the first result from a view query" do
239
+ @db.first!(@spec).should == @result
240
+ end
241
+
242
+ it "should raise an error if there are no results" do
243
+ @spec.stub(:process_results => [])
244
+ lambda {
245
+ @db.first!(@spec)
246
+ }.should raise_error(CouchPotato::NotFound)
247
+ end
248
+ end
249
+
210
250
  describe CouchPotato::Database, 'view' do
211
251
  before(:each) do
212
252
  @couchrest_db = stub('couchrest db').as_null_object
@@ -12,6 +12,12 @@ describe CouchPotato::Persistence::Json do
12
12
  sake = Drink.new(:alcohol => "18%")
13
13
  sake.to_hash[JSON.create_id].should eql("Drink")
14
14
  end
15
+
16
+ it "should not include _attachments if there are none" do
17
+ sake = Drink.new(:alcohol => "18%")
18
+ sake.to_hash.keys.should_not include('_attachments')
19
+ end
20
+
15
21
  end
16
22
 
17
23
  context '.json_create' do
@@ -26,53 +26,61 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
26
26
  it "should update a view when the map function has changed" do
27
27
  db = mock 'db', :get => {'views' => {'view2' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}}, :view => nil
28
28
  db.should_receive(:save_doc)
29
- CouchPotato::View::ViewQuery.new(db, 'design', :view2 => {:map => '<new map_code>', :recude => '<reduce_code>'}).query_view!
29
+ CouchPotato::View::ViewQuery.new(db, 'design', :view2 => {:map => '<new map_code>', :reduce => '<reduce_code>'}).query_view!
30
+ end
31
+
32
+ it "should not pass in a reduce key if there is no reduce function" do
33
+ db = mock 'db', :get => {'views' => {}}, :view => nil
34
+
35
+ db.should_receive(:save_doc).with('views' => {'view3' => {'map' => '<map code>'}})
36
+
37
+ CouchPotato::View::ViewQuery.new(db, 'design', :view3 => {:map => '<map code>', :reduce => nil}).query_view!
30
38
  end
31
39
 
32
40
  it "should update a view when the reduce function has changed" do
33
- db = mock 'db', :get => {'views' => {'view3' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}}, :view => nil
41
+ db = mock 'db', :get => {'views' => {'view4' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}}, :view => nil
34
42
  db.should_receive(:save_doc)
35
- CouchPotato::View::ViewQuery.new(db, 'design', :view3 => {:map => '<map_code>', :reduce => '<new reduce_code>'}).query_view!
43
+ CouchPotato::View::ViewQuery.new(db, 'design', :view4 => {:map => '<map_code>', :reduce => '<new reduce_code>'}).query_view!
36
44
  end
37
45
 
38
46
  it "should update a view when the list function has changed" do
39
47
  db = mock 'db', :get => {
40
- 'views' => {'view4' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
48
+ 'views' => {'view5' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
41
49
  'lists' => {'list1' => '<list_code>'}
42
50
  }, :view => nil
43
51
  db.should_receive(:save_doc)
44
- CouchPotato::View::ViewQuery.new(db, 'design', {:view4 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
52
+ CouchPotato::View::ViewQuery.new(db, 'design', {:view5 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
45
53
  end
46
54
 
47
55
  it "should update a view when there wasn't a list function but now there is one" do
48
56
  db = mock 'db', :get => {
49
- 'views' => {'view5' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
57
+ 'views' => {'view6' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
50
58
  }, :view => nil
51
59
  db.should_receive(:save_doc)
52
- CouchPotato::View::ViewQuery.new(db, 'design', {:view5 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
60
+ CouchPotato::View::ViewQuery.new(db, 'design', {:view6 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
53
61
  end
54
62
 
55
63
  it "should not update a view when there is a list function but no list function is passed" do
56
64
  db = mock 'db', :get => {
57
- 'views' => {'view6' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
65
+ 'views' => {'view7' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
58
66
  'lists' => {'list1' => '<list_code>'}
59
67
  }, :view => nil
60
68
  db.should_not_receive(:save_doc)
61
- CouchPotato::View::ViewQuery.new(db, 'design', {:view6 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
69
+ CouchPotato::View::ViewQuery.new(db, 'design', {:view7 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
62
70
  end
63
71
 
64
72
  it "should not update a view when there were no lists before and no list function is passed" do
65
73
  db = mock 'db', :get => {
66
- 'views' => {'view6' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
74
+ 'views' => {'view8' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
67
75
  }, :view => nil
68
76
  db.should_not_receive(:save_doc)
69
- CouchPotato::View::ViewQuery.new(db, 'design', {:view6 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
77
+ CouchPotato::View::ViewQuery.new(db, 'design', {:view8 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
70
78
  end
71
79
 
72
80
  it "should query CouchRest directly when querying a list" do
73
81
  db = stub('db').as_null_object
74
- CouchRest.should_receive(:get).with('http://127.0.0.1:5984/couch_potato_test/_design/my_design/_list/list1/view7?key=1')
75
- CouchPotato::View::ViewQuery.new(db, 'my_design', {:view7 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!(:key => 1)
82
+ CouchRest.should_receive(:get).with('http://127.0.0.1:5984/couch_potato_test/_design/my_design/_list/list1/view9?key=1')
83
+ CouchPotato::View::ViewQuery.new(db, 'my_design', {:view9 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!(:key => 1)
76
84
  end
77
85
 
78
86
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couch_potato
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
5
4
  prerelease:
6
- segments:
7
- - 0
8
- - 5
9
- - 1
10
- version: 0.5.1
5
+ version: 0.5.2
11
6
  platform: ruby
12
7
  authors:
13
8
  - Alexander Lang
@@ -15,7 +10,7 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-04-10 00:00:00 +02:00
13
+ date: 2011-04-18 00:00:00 +02:00
19
14
  default_executable:
20
15
  dependencies:
21
16
  - !ruby/object:Gem::Dependency
@@ -26,9 +21,6 @@ dependencies:
26
21
  requirements:
27
22
  - - ">="
28
23
  - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
24
  version: "0"
33
25
  type: :runtime
34
26
  version_requirements: *id001
@@ -40,11 +32,6 @@ dependencies:
40
32
  requirements:
41
33
  - - ">="
42
34
  - !ruby/object:Gem::Version
43
- hash: 21
44
- segments:
45
- - 1
46
- - 0
47
- - 1
48
35
  version: 1.0.1
49
36
  type: :runtime
50
37
  version_requirements: *id002
@@ -56,9 +43,6 @@ dependencies:
56
43
  requirements:
57
44
  - - ">="
58
45
  - !ruby/object:Gem::Version
59
- hash: 3
60
- segments:
61
- - 0
62
46
  version: "0"
63
47
  type: :runtime
64
48
  version_requirements: *id003
@@ -70,10 +54,6 @@ dependencies:
70
54
  requirements:
71
55
  - - ">="
72
56
  - !ruby/object:Gem::Version
73
- hash: 3
74
- segments:
75
- - 2
76
- - 0
77
57
  version: "2.0"
78
58
  type: :development
79
59
  version_requirements: *id004
@@ -85,9 +65,6 @@ dependencies:
85
65
  requirements:
86
66
  - - ">="
87
67
  - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
68
  version: "0"
92
69
  type: :development
93
70
  version_requirements: *id005
@@ -99,9 +76,6 @@ dependencies:
99
76
  requirements:
100
77
  - - ">="
101
78
  - !ruby/object:Gem::Version
102
- hash: 3
103
- segments:
104
- - 0
105
79
  version: "0"
106
80
  type: :development
107
81
  version_requirements: *id006
@@ -215,18 +189,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
215
189
  requirements:
216
190
  - - ">="
217
191
  - !ruby/object:Gem::Version
218
- hash: 3
219
- segments:
220
- - 0
221
192
  version: "0"
222
193
  required_rubygems_version: !ruby/object:Gem::Requirement
223
194
  none: false
224
195
  requirements:
225
196
  - - ">="
226
197
  - !ruby/object:Gem::Version
227
- hash: 3
228
- segments:
229
- - 0
230
198
  version: "0"
231
199
  requirements: []
232
200