couch_potato 1.21.0 → 1.22.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0460baa84b2605f60a5a954e246a9c839171b0f125e5bca929abf9e40a736bad
4
- data.tar.gz: b5ce4755ab00575bb348bdabedc678d9aad45a42469e202ce991e7f55d7aedd4
3
+ metadata.gz: a67f7979fa5b4e50e7b2a99229692134dddb0938d8aa8b9e194a3beecadc9baf
4
+ data.tar.gz: 781f887008ef098b75f91a642ec373bc43a1e4be46a4452182c335af8a173ed6
5
5
  SHA512:
6
- metadata.gz: c8c46fa595c3dbfb5d8f6d8206c3f250c2dd955f1df26ec0865abdb60c3f7294474f9579328a57c4d03db33f1050bb893024847e799715010abdf029aebcf357
7
- data.tar.gz: 4aea25697ff53ef8cffa72a3ca41c864abe1d1e62d539c634a2299679d86311872ad4efce1c14cf356b04131082ec50b8fc2bc0f1700a80e1a6bdc39cf0e7d28
6
+ metadata.gz: c1b30feb5418351056c70e7b2ae0f257e41339317cd0c20649046ad0a645efc42a52814e38fb7d9f6398e23eb16eef7710e25cbc4905db2fc13e85733d8fc3c5
7
+ data.tar.gz: 4c754a82ca5710332b363fbdfc75a813ac6212a2140993f67b271182e795e9e1540efae3cec1f06c9c356463f698266590b28c8ec9993e96bddea96cdbe5ef9f
@@ -0,0 +1,2 @@
1
+ [native_query_servers]
2
+ enable_erlang_query_server = true
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "Ruby 3.4",
3
+ "dockerComposeFile": "docker-compose.yml",
4
+ "service": "app",
5
+ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
6
+ "remoteUser": "vscode",
7
+ "containerEnv": {
8
+ "DATABASE": "http://admin:admin@127.0.0.1:5984/couch_potato_test"
9
+ },
10
+ "features": {
11
+ "ghcr.io/devcontainers/features/common-utils:2": {
12
+ "username": "vscode",
13
+ "userUid": "1000",
14
+ "userGid": "1000"
15
+ },
16
+ "ghcr.io/devcontainers/features/node:1": {}
17
+ }
18
+ }
@@ -0,0 +1,26 @@
1
+ services:
2
+ app:
3
+ image: ruby:3.4
4
+ volumes:
5
+ - ../..:/workspaces:z
6
+ command: sleep infinity
7
+ network_mode: service:couchdb
8
+ depends_on:
9
+ - couchdb
10
+
11
+ couchdb:
12
+ image: couchdb:3
13
+ restart: unless-stopped
14
+ entrypoint:
15
+ - /bin/bash
16
+ - -c
17
+ - cp /tmp/erlang-query-server.ini /opt/couchdb/etc/local.d/erlang-query-server.ini && exec tini -- /docker-entrypoint.sh /opt/couchdb/bin/couchdb
18
+ environment:
19
+ COUCHDB_USER: admin
20
+ COUCHDB_PASSWORD: admin
21
+ volumes:
22
+ - couchdb-data:/opt/couchdb/data
23
+ - ./couchdb/erlang-query-server.ini:/tmp/erlang-query-server.ini:ro,z
24
+
25
+ volumes:
26
+ couchdb-data:
data/CHANGES.md CHANGED
@@ -1,155 +1,172 @@
1
- ## Changes
1
+ # Changes
2
2
 
3
- # 1.21.0
3
+
4
+ ## 1.22.1
5
+
6
+ - fix lazy property loading calling overridden setters (use private `assign_attribute` instead)
7
+
8
+ ## couch_potato-rspec 4.4.0
9
+
10
+ - support multiple return values in `stub_view(...).and_return` for consecutive `view` / `first` / `first!` / `view_in_batches` calls
11
+
12
+ ## couch_potato-rspec 4.3.0
13
+
14
+ - support flex views in `stub_db` / `stub_view` (array returns a `FlexViewSpec::Results` stub with `docs`; `first`/`first!` stubbed on the db)
15
+
16
+ ## 1.22.00
17
+
18
+ - support `Database#first` / `#first!` for flex views
19
+
20
+ ## 1.21.0
4
21
 
5
22
  - add railties 8.1, Ruby 3.4 to CI
6
23
 
7
- # 1.20.1
24
+ ## 1.20.1
8
25
 
9
26
  - fix `database.save!` did not use passed block
10
27
 
11
- # 1.20.0
28
+ ## 1.20.0
12
29
 
13
30
  - add passing validation context to save methods
14
31
 
15
- # 1.19.2
32
+ ## 1.19.2
16
33
 
17
34
  - fix 404/409 error when querying single design doc with `digest_view_names` enabled
18
35
 
19
- # 1.19.1
36
+ ## 1.19.1
20
37
 
21
38
  - add digest to design doc name if `single_design_document` and `digest_view_names` are enabled
22
39
 
23
- # 1.19.0 / rspec-matchers 4.2.0
40
+ ## 1.19.0 / rspec-matchers 4.2.0
24
41
 
25
42
  - add `single_design_document` config option
26
43
  - remove support for lists and lib
27
44
 
28
- # 1.18.0
45
+ ## 1.18.0
29
46
 
30
47
  - add testing Rails 7.2/8 on CI
31
48
  - change gemspec to allow for Rails 8
32
49
  - remove support for Rails < 7.2
33
50
 
34
- # 1.17.0
51
+ ## 1.17.0
35
52
 
36
53
  - filter out nil ids for loading multiple documents
37
54
  - cache nil documents
38
55
 
39
- # 1.16.0
56
+ ## 1.16.0
40
57
 
41
58
  - add payload to ActiveSupport instrumentation calls
42
59
  - only notify load.cached when there are cached documents
43
60
 
44
- # 1.15.0
61
+ ## 1.15.0
45
62
 
46
63
  - cache loading multiple documents
47
64
  - keep the database cache when switching to another database and back to the original one
48
65
 
49
- # 1.14.0
66
+ ## 1.14.0
50
67
 
51
68
  - add database_collection to models to help avoid n+1 requests
52
69
 
53
- # 1.13.0
70
+ ## 1.13.0
54
71
 
55
72
  - add Ruby 3.2 support
56
73
  - remove Ruby 2.7 support
57
74
  - add active_support 7.1 support
58
75
  - remove active_support 6.x support
59
76
 
60
- # 1.12.1
77
+ ## 1.12.1
61
78
 
62
79
  - re-enable aliases when parsing config yaml file
63
80
 
64
- # 1.12.0
81
+ ## 1.12.0
65
82
 
66
83
  - remove active_support 5.x
67
84
  - add Ruby 3.1 support (active_support 6.1, 7.0)
68
85
 
69
- # 1.11.0
86
+ ## 1.11.0
70
87
 
71
88
  - improve view_in_batches performance by switching to using startkey_docid over skip
72
89
 
73
- ### 1.10.1
90
+ ## 1.10.1
74
91
 
75
92
  - support passing an empty array to CouchPotato::Database#load
76
93
 
77
- ### 1.10.0
94
+ ## 1.10.0
78
95
 
79
96
  - add spec/support for Rails 7
80
97
 
81
- ### 1.9.0
98
+ ## 1.9.0
82
99
 
83
100
  - add spec/support for Rails 6.1
84
101
  - add caching Couchrest connections to reduce total number created
85
102
 
86
- ### 1.8.0
103
+ ## 1.8.0
87
104
 
88
105
  - remove not saving model if it is not dirty. this could lead to missed document updates if the document has been updated in a different process in-between being loaded and saved in the current process.
89
106
 
90
107
  - remove deep dirty tracking
91
108
 
92
- ### 1.7.1
109
+ ## 1.7.1
93
110
 
94
111
  - added support for properties of type Integer
95
112
 
96
- ### 1.7.0
113
+ ## 1.7.0
97
114
 
98
115
  - added `_revisions` method that returns all available revisions of a document.
99
116
 
100
- ### 1.6.4
117
+ ## 1.6.4
101
118
 
102
119
  - bug fix for accessing inherited properties (Alexander Lang)
103
120
 
104
- ### 1.6.3
121
+ ## 1.6.3
105
122
 
106
123
  - added ActiveSupport instrumentation (Alexander Lang)
107
124
 
108
- ### 1.6.2
125
+ ## 1.6.2
109
126
 
110
127
  - view digest bugfix (Alexander Lang)
111
128
 
112
- ### 1.6.1
129
+ ## 1.6.1
113
130
 
114
131
  - added option to add digests to a single view (Alexander Lang)
115
132
 
116
- ### 1.6.0
133
+ ## 1.6.0
117
134
 
118
135
  - added global option to add digests to view names (Alexander Lang)
119
136
 
120
- ### 1.5.1
137
+ ## 1.5.1
121
138
 
122
139
  - updated CouchRest to 2.0.0.rc3 in order to re-use http connections. Performance improvements. (Thilo Utke)
123
140
  - added passing params to lists (Alexander Lang)
124
141
 
125
- ### 1.5.0
142
+ ## 1.5.0
126
143
 
127
144
  - Moved RSpec matchers into couch_potato-rspec gem. This way, people not using RSpec don't need to install the helpers, plus we can release separate matchers for RSpec 2 and 3.
128
145
 
129
- ### 1.4.0
146
+ ## 1.4.0
130
147
 
131
148
  - Added support for passing the model to blocks for computing the default value of a property (Alexander Lang)
132
149
 
133
- ### 1.3.0
150
+ ## 1.3.0
134
151
 
135
152
  - Add support for built-in couchdb reduce functions in map reduce specs (Andy Morris)
136
153
  - Make specs handle CommonJS modules via module.exports as well as exports (Andy Morris)
137
154
  - Changed #attributes to return a HashWithIndifferentAccess (Owen Davies)
138
155
 
139
- ### 1.2.0
156
+ ## 1.2.0
140
157
 
141
158
  - adds optional deep dirty tracking (andymorris)
142
159
  - fixes an exception when deleting an already deleted document (Alexander Lang)
143
160
 
144
- ### 1.1.4
161
+ ## 1.1.4
145
162
 
146
163
  - Removes the dependency to json/add/core (cstettner)
147
164
 
148
- ### 1.1.3
165
+ ## 1.1.3
149
166
 
150
167
  - removes check if database exists to avoid lots of additional requests (Alexander Lang)
151
168
 
152
- ### 1.1.2
169
+ ## 1.1.2
153
170
 
154
171
  - fixes `CouchPotato.models` did not include subclasses
155
172
  - adds `CouchPotato.use` (Daniel Lohse)
@@ -157,19 +174,19 @@
157
174
  - adds `CouchPotato::Config.database_host` for using multiple databases in a project (Daniel Lohse)
158
175
  - makes `cast_native` cast floats with no leading digits (wrshawn)
159
176
 
160
- ### 1.1.1
177
+ ## 1.1.1
161
178
 
162
179
  - fixes properties were leaked to sibling classes (Alexander Lang)
163
180
 
164
- ### 1.1.0
181
+ ## 1.1.0
165
182
 
166
183
  - adds conflict handling for Database#save/destroy (Alexander Lang)
167
184
 
168
- ### 1.0.1
185
+ ## 1.0.1
169
186
 
170
187
  - fixes error when bulk loaded document does not respond to database= (Alexander Lang)
171
188
 
172
- ### 1.0.0
189
+ ## 1.0.0
173
190
 
174
191
  - adds `reload` method (Alexander Lang)
175
192
  - removes `total_rows` from database results (Alexander Lang)
@@ -183,11 +200,11 @@
183
200
  - adds suppot for BigDecimal properties (Fredrik Rubensson)
184
201
  - adds support for 2.0, Rubinius, 1.9.3, drops Ruby 1.8, 1.9.2
185
202
 
186
- ### 0.7.1
203
+ ## 0.7.1
187
204
 
188
205
  - fixes a bug when trying to bulk-load non-existant documents
189
206
 
190
- ### 0.7.0
207
+ ## 0.7.0
191
208
 
192
209
  - ActiveSupport/Rails 3.2 compatibility (Alexander Lang)
193
210
  - removed Object#try, String#blank? as they are part of ActiveSupport - ActiveSupport's try behaves differently than the couch potato implementation so this change might break your app (now calling a non-existant method on a non-nil raises a NoMethodError, before it did not) (Alexander Lang)
@@ -201,168 +218,168 @@
201
218
  - don't crash, only warn if couchdb.yml is missing (Alexander Lang)
202
219
  - use the therubyracer gem to run view specs instead of relying on a `js` executable (Alexander Lang)
203
220
 
204
- ### 0.6.0
221
+ ## 0.6.0
205
222
 
206
223
  - ActiveSupport/Rails 3.1 compatibility (Maximilian Mack)
207
224
  - fix no such file to load with json/add/rails (Simone Carletti)
208
225
 
209
- ### 0.5.7
226
+ ## 0.5.7
210
227
 
211
228
  - support CouchPotato::Database#first/#first! calls when using `stub_db` from tests (langalex)
212
229
  - support RSpec2 block syntax in `stub_db` (langalex)
213
230
 
214
- ### 0.5.6
231
+ ## 0.5.6
215
232
 
216
233
  - remove the stale parameter from a view query if it's nil, as couchdb only allows stale to be ok or update_after (langalex)
217
234
 
218
- ### 0.5.5
235
+ ## 0.5.5
219
236
 
220
237
  - support for split_design_documents_per_view (jweiss)
221
238
  - errors now returns a Hash instead of an Array (bterkuile)
222
239
  - support passing in list names as symbols in view specs (langalex)
223
240
 
224
- ### 0.5.4
241
+ ## 0.5.4
225
242
 
226
243
  - cast 'false' to false for boolean properties (langalex)
227
244
 
228
- ### 0.5.3
245
+ ## 0.5.3
229
246
 
230
247
  - added CouchPotato::Database.load! (langalex)
231
248
 
232
- ### 0.5.2
249
+ ## 0.5.2
233
250
 
234
251
  - added CouchPotato::Database#first and #first! methods (langalex)
235
252
  - added workaround for BigCouch/Cloudant to not add null reduce functions to views (langalex)
236
253
  - don't add \_attachments if there are none (langalex)
237
254
 
238
- ### 0.5.1
255
+ ## 0.5.1
239
256
 
240
257
  - fixed issues with tzinfo gem (Bernd Ahlers)
241
258
 
242
- ### 0.5.0
259
+ ## 0.5.0
243
260
 
244
261
  - time zone support (Time properties are now converted to current Time.zone) (langalex)
245
262
  - lazy property initialization (performance!) (langalex)
246
263
  - active_model is now the default validation framework (langalex)
247
264
 
248
- ### 0.4.0
265
+ ## 0.4.0
249
266
 
250
267
  - ruby 1.9.2 compatibility (langalex)
251
268
  - couch potato objects now behave correctly when used as keys in Hashes (langalex)
252
269
  - use as_json instead of to_s(:json), which is the rails way
253
270
  - use ActiveModel dirty tracking (langalex) - this means no more "deep tracking", e.g. `user.tags << 'new_tag'; user.dirty? # false`
254
271
 
255
- ### 0.3.2
272
+ ## 0.3.2
256
273
 
257
274
  - support yielding to blocks on #initialize (martinrehfeld)
258
275
  - support for negative numbers in Fixnum/Float properties (langalex)
259
276
 
260
- ### 0.3.1
277
+ ## 0.3.1
261
278
 
262
279
  - ActiveModel callbacks (kazjote)
263
280
  - do not use Rails.env in initializer as it will free Rails.env for all times and in Rails 2.3.x apps it will be called too early thus always beeing development (jweiss)
264
281
  - ruby 1.9.2 compatibility (langalex)
265
282
  - can configure validation framework in couchdb.yml, process couchdb.yml with erb (langalex)
266
283
 
267
- ### 0.3.0
284
+ ## 0.3.0
268
285
 
269
286
  - support for lists (langalex)
270
287
 
271
- ### 0.2.32
288
+ ## 0.2.32
272
289
 
273
290
  - added persisted? and to_key for proper ActiveModel compliance (thilo)
274
291
  - id setter (jhohertz-work)
275
292
  - load document ids if include_documents is false (jweiss)
276
293
  - persist given created_at/updated_at instead of Time.now (langalex)
277
294
 
278
- ### 0.2.31
295
+ ## 0.2.31
279
296
 
280
297
  - Removed requirement for validatable gem. Allows for using more uptodate versions of the library, or doesn't install it when you're using ActiveModel. (mattmatt)
281
298
  - fixed callbacks of super classes were not run (langalex)
282
299
 
283
- ### 0.2.30
300
+ ## 0.2.30
284
301
 
285
302
  - pass in multiple keys when querying a view (langalex)
286
303
 
287
- ### 0.2.29
304
+ ## 0.2.29
288
305
 
289
306
  - nicer inspect() for models (mattmatt)
290
307
  - fixed (re)reduce for property views wasn't working (langalex)
291
308
 
292
- ### 0.2.28
309
+ ## 0.2.28
293
310
 
294
311
  - fixed reloading nested classes (langalex)
295
312
  - fixed constant missing error when loading models with uninitialized classes via views (langalex)
296
313
  - added rspec helpers for stubbing out views (langalex)
297
314
  - fixed design document names for nested model classes (svenfuchs)
298
315
 
299
- ### 0.2.27
316
+ ## 0.2.27
300
317
 
301
318
  - workaround for Rails apps using bundler: database name was not initialized from couchdb.yml (langalex)
302
319
 
303
- ### 0.2.26
320
+ ## 0.2.26
304
321
 
305
322
  - added to_s(:json) to Date and Time to be able to get properly formatted dates/times for searching with dates/times (langalex)
306
323
  - all times are now stored as UTC (langalex)
307
324
  - added support for Float attributes (arbovm)
308
325
 
309
- ### 0.2.25
326
+ ## 0.2.25
310
327
 
311
328
  - automatic view updates: when you change the definition of a view couch potato will now update the design document in the database (langalex)
312
329
  - support for properties of type Date, better support for Time (langalex)
313
330
  - support for default reduce count methods in custom views (jweiss)
314
331
 
315
- ### 0.2.24
332
+ ## 0.2.24
316
333
 
317
334
  - persistent instances can now be marked as dirty with #is_dirty (langalex)
318
335
 
319
- ### 0.2.23
336
+ ## 0.2.23
320
337
 
321
338
  - Couch Potato models now conform to the ActiveModel interface when ActiveModel is installed, see http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/ (langalex)
322
339
  - fixed error with dirty tracking and BigDecimals (thilo)
323
340
  - added the ability to use ActiveModel validations instead of validatable (martinrehfeld)
324
341
 
325
- ### 0.2.22
342
+ ## 0.2.22
326
343
 
327
344
  - fixed properties with default values returned default when a blank value like '' or [] was set (langalex)
328
345
 
329
- ### 0.2.21
346
+ ## 0.2.21
330
347
 
331
348
  - automatically set a database instance on results of CouchPotato::Database#view (langalex)
332
349
  - improved auto loading of unloaded constants - can now load constants that have never been loaded before (langalex)
333
350
  - raise exception on invalid parameters passed to a couchdb view query (langalex)
334
351
  - when querying a view: pass in ranges as key instead of startkey/endkey, pass in plain value instead of hash with key (langalex)
335
352
 
336
- ### 0.2.20
353
+ ## 0.2.20
337
354
 
338
355
  - support for :boolean properties (jweiss)
339
356
  - return the total_rows when querying a view (langalex)
340
357
 
341
- ### 0.2.19
358
+ ## 0.2.19
342
359
 
343
360
  - added conditions to views (langalex)
344
361
 
345
- ### 0.2.18
362
+ ## 0.2.18
346
363
 
347
364
  - set Fixnum property to nil when given a blank string (langalex)
348
365
 
349
- ### 0.2.17
366
+ ## 0.2.17
350
367
 
351
368
  - fixed nil attributes were omitted in json (jweiss, mattmatt)
352
369
  - support for properties of type Fixnum (langalex)
353
370
 
354
- ### 0.2.16
371
+ ## 0.2.16
355
372
 
356
373
  - fixed problem with classes being not loaded in rails development mode (langalex)
357
374
  - fixed persist boolean false value (bernd)
358
375
 
359
- ### 0.2.15
376
+ ## 0.2.15
360
377
 
361
378
  - ability to change the name of the attribute that stores the ruby class in the documents by setting JSON.create_id (lennart)
362
379
  - fixed double loading issue with bundler (jweiss)
363
380
  - fixed an issue with setting attachments (endor)
364
381
 
365
- ### 0.2.13
382
+ ## 0.2.13
366
383
 
367
384
  - support adding errors in before_validation callbacks (mattmatt)
368
385
  - support for inheritance (mattmatt)
@@ -370,11 +387,11 @@
370
387
  - improved (de)serialization now supports deserializing nested objects (railsbros, specs by hagenburger)
371
388
  - RSpec matchers for testing map/reduce functions (langalex)
372
389
 
373
- ### 0.2.10
390
+ ## 0.2.10
374
391
 
375
392
  - fixed bug with hardcoded timezone
376
393
 
377
- ### 0.2.9
394
+ ## 0.2.9
378
395
 
379
396
  - allow to overwrite attribute accessor of properties and use super to call the original accessors
380
397
  - allow read access to attributes that are present in the Couchdb document but not defined as properties
data/couch_potato.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.add_dependency 'activemodel', ['>= 7.2', '< 8.2']
17
17
  s.add_dependency 'couchrest', '~>2.0.0'
18
18
  s.add_dependency 'json', '~> 2.3'
19
+ s.add_dependency 'ostruct'
19
20
 
20
21
  s.add_development_dependency 'rake', '~>12.0'
21
22
  s.add_development_dependency 'rspec', '~>3.12.0'
@@ -96,7 +96,8 @@ module CouchPotato
96
96
  # returns the first result from a #view query or nil
97
97
  def first(spec)
98
98
  spec.view_parameters = spec.view_parameters.merge({ limit: 1 })
99
- view(spec).first
99
+ result = view(spec)
100
+ flex_view?(spec) ? result.docs.first : result.first
100
101
  end
101
102
 
102
103
  # returns th first result from a #view or raises CouchPotato::NotFound
@@ -240,6 +241,10 @@ module CouchPotato
240
241
 
241
242
  private
242
243
 
244
+ def flex_view?(spec)
245
+ spec.is_a?(CouchPotato::View::FlexViewSpec)
246
+ end
247
+
243
248
  def copy_clear_cache_proc
244
249
  lambda { |db|
245
250
  next unless cache
@@ -12,6 +12,13 @@ module CouchPotato
12
12
  value
13
13
  end
14
14
  end
15
+
16
+ def assign_attribute(name, value)
17
+ property = self.class.properties.find_property(name)
18
+ typecasted_value = type_caster.cast(value, property.type)
19
+ send("#{name}_will_change!") unless @skip_dirty_tracking || typecasted_value == send(name)
20
+ instance_variable_set("@#{name}", typecasted_value)
21
+ end
15
22
  end
16
23
 
17
24
  class SimpleProperty #:nodoc:
@@ -19,7 +26,6 @@ module CouchPotato
19
26
 
20
27
  def initialize(owner_clazz, name, options = {})
21
28
  self.name = name
22
- @setter_name = "#{name}="
23
29
  self.type = options[:type]
24
30
  self.default_value = options[:default]
25
31
  @type_caster = TypeCaster.new
@@ -29,8 +35,7 @@ module CouchPotato
29
35
  end
30
36
 
31
37
  def build(object, json)
32
- value = json[name]
33
- object.send @setter_name, value
38
+ object.send(:assign_attribute, name, json[name])
34
39
  end
35
40
 
36
41
  def serialize(json, object)
@@ -77,9 +82,7 @@ module CouchPotato
77
82
  end
78
83
 
79
84
  define_method "#{name}=" do |value|
80
- typecasted_value = type_caster.cast(value, options[:type])
81
- send("#{name}_will_change!") unless @skip_dirty_tracking || typecasted_value == send(name)
82
- self.instance_variable_set(ivar_name, typecasted_value)
85
+ assign_attribute(name, value)
83
86
  end
84
87
 
85
88
  define_method "#{name}?" do
@@ -1,4 +1,4 @@
1
1
  module CouchPotato
2
- VERSION = '1.21.0'.freeze
3
- RSPEC_VERSION = '4.2.0'.freeze
2
+ VERSION = '1.22.1'.freeze
3
+ RSPEC_VERSION = '4.4.0'.freeze
4
4
  end
@@ -98,6 +98,11 @@ module CouchPotato
98
98
  delegate :view_name, :view_parameters, :design_document, :map_function,
99
99
  :reduce_function, :language, to: :view_spec_delegate
100
100
 
101
+ def view_parameters=(params)
102
+ @view_parameters = params
103
+ @view_spec_delegate.view_parameters = params if @view_spec_delegate
104
+ end
105
+
101
106
  def process_results(results)
102
107
  results = Results.new(results)
103
108
  results.extend @extend_results_module if @extend_results_module
@@ -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 :normalized_title
15
16
  property :diameter, type: Float
16
17
 
17
18
  def overwritten_read
@@ -21,6 +22,10 @@ class Watch
21
22
  def overwritten_write=(value)
22
23
  super value.to_s
23
24
  end
25
+
26
+ def normalized_title=(value)
27
+ super(value.to_s.upcase)
28
+ end
24
29
  end
25
30
 
26
31
  class Address2 < Address
@@ -59,6 +64,12 @@ describe 'properties' do
59
64
  expect(Watch.new(:overwritten_write => 1).overwritten_write).to eq('1')
60
65
  end
61
66
 
67
+ it "does not call overwritten write accessors when loading from a document" do
68
+ watch = Watch.json_create('normalized_title' => 'Hello', JSON.create_id => 'Watch')
69
+
70
+ expect(watch.normalized_title).to eq('Hello')
71
+ end
72
+
62
73
  it "should return the property names" do
63
74
  expect(Comment.property_names).to eq([:created_at, :updated_at, :title])
64
75
  end
@@ -414,6 +414,85 @@ describe CouchPotato::Database, 'first!' do
414
414
  end
415
415
  end
416
416
 
417
+ describe CouchPotato::Database, 'first with flex view' do
418
+ before(:each) do
419
+ @couchrest_db = double('couchrest db').as_null_object
420
+ @db = CouchPotato::Database.new(@couchrest_db)
421
+ @doc = double('doc')
422
+ @view_parameters = { include_docs: true }
423
+ @results = instance_double(CouchPotato::View::FlexViewSpec::Results, docs: [@doc])
424
+ allow(@results).to receive(:database=)
425
+ @spec = instance_double(
426
+ CouchPotato::View::FlexViewSpec,
427
+ klass: 'FlexFirstModel',
428
+ view_name: 'by_name',
429
+ design_document: 'flex_first_model',
430
+ map_function: 'map',
431
+ reduce_function: nil,
432
+ language: :javascript,
433
+ process_results: @results
434
+ )
435
+ allow(@spec).to receive(:view_parameters) { @view_parameters }
436
+ allow(@spec).to receive(:view_parameters=) { |params| @view_parameters = params }
437
+ allow(@spec).to receive(:is_a?).with(CouchPotato::View::FlexViewSpec).and_return(true)
438
+ allow(CouchPotato::View::ViewQuery).to receive_messages(
439
+ new: double('view query', query_view!: { 'rows' => [{ 'doc' => @doc }] })
440
+ )
441
+ end
442
+
443
+ it 'returns the first doc from a flex view' do
444
+ expect(@db.first(@spec)).to eq(@doc)
445
+ end
446
+
447
+ it 'returns nil if there are no docs' do
448
+ allow(@results).to receive(:docs).and_return([])
449
+ expect(@db.first(@spec)).to be_nil
450
+ end
451
+
452
+ it 'sets limit: 1 on the view parameters' do
453
+ @db.first(@spec)
454
+ expect(@view_parameters[:limit]).to eq(1)
455
+ end
456
+ end
457
+
458
+ describe CouchPotato::Database, 'first! with flex view' do
459
+ before(:each) do
460
+ @couchrest_db = double('couchrest db').as_null_object
461
+ @db = CouchPotato::Database.new(@couchrest_db)
462
+ @doc = double('doc')
463
+ @view_parameters = { include_docs: true }
464
+ @results = instance_double(CouchPotato::View::FlexViewSpec::Results, docs: [@doc])
465
+ allow(@results).to receive(:database=)
466
+ @spec = instance_double(
467
+ CouchPotato::View::FlexViewSpec,
468
+ klass: 'FlexFirstBangModel',
469
+ view_name: 'by_name',
470
+ design_document: 'flex_first_bang_model',
471
+ map_function: 'map',
472
+ reduce_function: nil,
473
+ language: :javascript,
474
+ process_results: @results
475
+ )
476
+ allow(@spec).to receive(:view_parameters) { @view_parameters }
477
+ allow(@spec).to receive(:view_parameters=) { |params| @view_parameters = params }
478
+ allow(@spec).to receive(:is_a?).with(CouchPotato::View::FlexViewSpec).and_return(true)
479
+ allow(CouchPotato::View::ViewQuery).to receive_messages(
480
+ new: double('view query', query_view!: { 'rows' => [{ 'doc' => @doc }] })
481
+ )
482
+ end
483
+
484
+ it 'returns the first doc from a flex view' do
485
+ expect(@db.first!(@spec)).to eq(@doc)
486
+ end
487
+
488
+ it 'raises an error if there are no docs' do
489
+ allow(@results).to receive(:docs).and_return([])
490
+ expect do
491
+ @db.first!(@spec)
492
+ end.to raise_error(CouchPotato::NotFound)
493
+ end
494
+ end
495
+
417
496
  describe CouchPotato::Database, 'view' do
418
497
  before(:each) do
419
498
  @couchrest_db = double('couchrest db').as_null_object
@@ -41,4 +41,19 @@ RSpec.describe CouchPotato::View::FlexViewSpec::Results, '#docs' do
41
41
 
42
42
  it 'returns the docs' do
43
43
  end
44
+ end
45
+
46
+ RSpec.describe CouchPotato::View::FlexViewSpec, '#view_parameters=' do
47
+ it 'updates view parameters on the delegate' do
48
+ klass = Class.new do
49
+ def self.name
50
+ 'FlexViewParamsModel'
51
+ end
52
+ end
53
+ spec = CouchPotato::View::FlexViewSpec.new(klass, 'by_x', { key: :x }, {})
54
+
55
+ spec.view_parameters = spec.view_parameters.merge(limit: 1)
56
+
57
+ expect(spec.view_parameters[:limit]).to eq(1)
58
+ end
44
59
  end
@@ -9,6 +9,12 @@ class WithStubbedView
9
9
  view :stubbed_view, key: :x
10
10
  end
11
11
 
12
+ class WithStubbedFlexView
13
+ include CouchPotato::Persistence
14
+
15
+ view :stubbed_flex_view, type: :flex, key: :x
16
+ end
17
+
12
18
  describe 'stubbing the db' do
13
19
  it 'replaces CouchPotato.database with a double' do
14
20
  CouchPotato.stub_db
@@ -37,6 +43,40 @@ describe 'stubbing a view' do
37
43
  expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq([:result])
38
44
  end
39
45
 
46
+ it 'returns successive values on consecutive view calls' do
47
+ @db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:first], [:second])
48
+
49
+ expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq([:first])
50
+ expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq([:second])
51
+ end
52
+
53
+ it 'returns successive first values on consecutive first calls' do
54
+ @db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:a], [:b])
55
+
56
+ expect(@db.first(WithStubbedView.stubbed_view('123'))).to eq(:a)
57
+ expect(@db.first(WithStubbedView.stubbed_view('123'))).to eq(:b)
58
+ end
59
+
60
+ it 'returns successive values on consecutive first! calls and raises for a nil first value' do
61
+ @db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:a], [], [:b])
62
+
63
+ expect(@db.first!(WithStubbedView.stubbed_view('123'))).to eq(:a)
64
+ expect { @db.first!(WithStubbedView.stubbed_view('123')) }.to raise_error(CouchPotato::NotFound)
65
+ expect(@db.first!(WithStubbedView.stubbed_view('123'))).to eq(:b)
66
+ end
67
+
68
+ it 'yields successive return values on consecutive view_in_batches calls' do
69
+ @db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:a, :b], [:c])
70
+
71
+ expect do |b|
72
+ @db.view_in_batches(WithStubbedView.stubbed_view('123'), batch_size: 2, &b)
73
+ end.to yield_successive_args([:a, :b])
74
+
75
+ expect do |b|
76
+ @db.view_in_batches(WithStubbedView.stubbed_view('123'), batch_size: 2, &b)
77
+ end.to yield_successive_args([:c])
78
+ end
79
+
40
80
  it 'stubs the database to return the first fake result' do
41
81
  expect(@db.first(WithStubbedView.stubbed_view('123'))).to eq(:result)
42
82
  expect(@db.first!(WithStubbedView.stubbed_view('123'))).to eq(:result)
@@ -96,3 +136,55 @@ describe 'stubbing a view' do
96
136
  expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq(:results)
97
137
  end
98
138
  end
139
+
140
+ describe 'stubbing a flex view' do
141
+ before(:each) do
142
+ @db = CouchPotato.stub_db
143
+ @db.stub_view(WithStubbedFlexView, :stubbed_flex_view).with('123').and_return([:result])
144
+ end
145
+
146
+ it 'stubs the database to return a results stub with docs when given an array' do
147
+ expect(@db.view(WithStubbedFlexView.stubbed_flex_view('123')).docs).to eq([:result])
148
+ end
149
+
150
+ it 'stubs the database to return the first fake result' do
151
+ expect(@db.first(WithStubbedFlexView.stubbed_flex_view('123'))).to eq(:result)
152
+ expect(@db.first!(WithStubbedFlexView.stubbed_flex_view('123'))).to eq(:result)
153
+ end
154
+
155
+ it 'returns successive results stubs on consecutive view calls' do
156
+ @db.stub_view(WithStubbedFlexView, :stubbed_flex_view).with('123').and_return([:first], [:second])
157
+
158
+ expect(@db.view(WithStubbedFlexView.stubbed_flex_view('123')).docs).to eq([:first])
159
+ expect(@db.view(WithStubbedFlexView.stubbed_flex_view('123')).docs).to eq([:second])
160
+ end
161
+
162
+ it 'returns successive first values on consecutive first calls' do
163
+ @db.stub_view(WithStubbedFlexView, :stubbed_flex_view).with('123').and_return([:a], [:b])
164
+
165
+ expect(@db.first(WithStubbedFlexView.stubbed_flex_view('123'))).to eq(:a)
166
+ expect(@db.first(WithStubbedFlexView.stubbed_flex_view('123'))).to eq(:b)
167
+ end
168
+
169
+ it 'returns successive values on consecutive first! calls and raises for a nil first value' do
170
+ @db.stub_view(WithStubbedFlexView, :stubbed_flex_view).with('123').and_return([:a], [], [:b])
171
+
172
+ expect(@db.first!(WithStubbedFlexView.stubbed_flex_view('123'))).to eq(:a)
173
+ expect { @db.first!(WithStubbedFlexView.stubbed_flex_view('123')) }.to raise_error(CouchPotato::NotFound)
174
+ expect(@db.first!(WithStubbedFlexView.stubbed_flex_view('123'))).to eq(:b)
175
+ end
176
+
177
+ it 'raises from db.first! when the array is empty' do
178
+ @db.stub_view(WithStubbedFlexView, :stubbed_flex_view).and_return([])
179
+
180
+ expect do
181
+ @db.first!(WithStubbedFlexView.stubbed_flex_view)
182
+ end.to raise_error(CouchPotato::NotFound)
183
+ end
184
+
185
+ it 'returns a non-array return value directly' do
186
+ @db.stub_view(WithStubbedFlexView, :stubbed_flex_view).with('123').and_return(:reduced)
187
+
188
+ expect(@db.view(WithStubbedFlexView.stubbed_flex_view('123'))).to eq(:reduced)
189
+ end
190
+ end
data/spec/views_spec.rb CHANGED
@@ -345,6 +345,26 @@ describe 'views' do
345
345
 
346
346
  expect(custom).to eq([100, 200])
347
347
  end
348
+
349
+ it 'returns the first doc via Database#first' do
350
+ @db.save_document Build.new(id: 'b1', time: '1')
351
+ @db.save_document Build.new(id: 'b2', time: '2')
352
+
353
+ doc = @db.first(Build.flex_with_key(include_docs: true))
354
+
355
+ expect(doc).to be_a(Build)
356
+ expect(doc.id).to eq('b1')
357
+ end
358
+
359
+ it 'returns nil from Database#first when there are no results' do
360
+ expect(@db.first(Build.flex_with_key(include_docs: true))).to be_nil
361
+ end
362
+
363
+ it 'raises from Database#first! when there are no results' do
364
+ expect do
365
+ @db.first!(Build.flex_with_key(include_docs: true))
366
+ end.to raise_error(CouchPotato::NotFound)
367
+ end
348
368
  end
349
369
 
350
370
  describe 'inherited views' do
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couch_potato
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 1.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Lang
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-01-13 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activemodel
@@ -58,6 +57,20 @@ dependencies:
58
57
  - - "~>"
59
58
  - !ruby/object:Gem::Version
60
59
  version: '2.3'
60
+ - !ruby/object:Gem::Dependency
61
+ name: ostruct
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :runtime
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
61
74
  - !ruby/object:Gem::Dependency
62
75
  name: rake
63
76
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +133,9 @@ executables: []
120
133
  extensions: []
121
134
  extra_rdoc_files: []
122
135
  files:
136
+ - ".devcontainer/couchdb/erlang-query-server.ini"
137
+ - ".devcontainer/devcontainer.json"
138
+ - ".devcontainer/docker-compose.yml"
123
139
  - ".github/workflows/ruby.yml"
124
140
  - ".gitignore"
125
141
  - CHANGES.md
@@ -216,7 +232,6 @@ files:
216
232
  homepage: http://github.com/langalex/couch_potato
217
233
  licenses: []
218
234
  metadata: {}
219
- post_install_message:
220
235
  rdoc_options: []
221
236
  require_paths:
222
237
  - lib
@@ -231,8 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
246
  - !ruby/object:Gem::Version
232
247
  version: '0'
233
248
  requirements: []
234
- rubygems_version: 3.4.7
235
- signing_key:
249
+ rubygems_version: 3.6.9
236
250
  specification_version: 4
237
251
  summary: Ruby persistence layer for CouchDB
238
252
  test_files: