couch_potato 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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