simply_couch 0.1.0

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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +182 -0
  3. data/LICENSE.txt +15 -0
  4. data/README.md +294 -0
  5. data/lib/core_ext/date.rb +15 -0
  6. data/lib/core_ext/time.rb +23 -0
  7. data/lib/simply_couch/class_methods_base.rb +72 -0
  8. data/lib/simply_couch/has_attachment.rb +225 -0
  9. data/lib/simply_couch/include_relation.rb +160 -0
  10. data/lib/simply_couch/instance_methods.rb +356 -0
  11. data/lib/simply_couch/locale/en.yml +5 -0
  12. data/lib/simply_couch/model/ancestry.rb +307 -0
  13. data/lib/simply_couch/model/association_property.rb +26 -0
  14. data/lib/simply_couch/model/attachments.rb +90 -0
  15. data/lib/simply_couch/model/belongs_to.rb +140 -0
  16. data/lib/simply_couch/model/database.rb +209 -0
  17. data/lib/simply_couch/model/embedded_in.rb +196 -0
  18. data/lib/simply_couch/model/find_by.rb +202 -0
  19. data/lib/simply_couch/model/finders.rb +77 -0
  20. data/lib/simply_couch/model/has_and_belongs_to_many.rb +223 -0
  21. data/lib/simply_couch/model/has_many.rb +177 -0
  22. data/lib/simply_couch/model/has_many_embedded.rb +187 -0
  23. data/lib/simply_couch/model/has_one.rb +75 -0
  24. data/lib/simply_couch/model/pagination.rb +25 -0
  25. data/lib/simply_couch/model/pagination_options.rb +55 -0
  26. data/lib/simply_couch/model/persistence.rb +411 -0
  27. data/lib/simply_couch/model/properties.rb +11 -0
  28. data/lib/simply_couch/model/validations.rb +28 -0
  29. data/lib/simply_couch/model/view/base_view_spec.rb +115 -0
  30. data/lib/simply_couch/model/view/custom_view_spec.rb +49 -0
  31. data/lib/simply_couch/model/view/custom_views.rb +50 -0
  32. data/lib/simply_couch/model/view/lists.rb +25 -0
  33. data/lib/simply_couch/model/view/model_view_spec.rb +106 -0
  34. data/lib/simply_couch/model/view/properties_view_spec.rb +53 -0
  35. data/lib/simply_couch/model/view/raw_view_spec.rb +30 -0
  36. data/lib/simply_couch/model/view/view_query.rb +98 -0
  37. data/lib/simply_couch/model/view.rb +8 -0
  38. data/lib/simply_couch/model/views/array_property_view_spec.rb +26 -0
  39. data/lib/simply_couch/model/views/deleted_model_view_spec.rb +43 -0
  40. data/lib/simply_couch/model/views.rb +2 -0
  41. data/lib/simply_couch/model.rb +195 -0
  42. data/lib/simply_couch/rake.rb +23 -0
  43. data/lib/simply_couch/storage.rb +147 -0
  44. data/lib/simply_couch.rb +26 -0
  45. metadata +144 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ae31eaff1df5b1b5f92f31fc03ed41f757e8d790d5ed6a288bc57f8f15b41f80
4
+ data.tar.gz: 337be26593098ec144a9f89ea94f21e9614dea96ad44f0b6933191fb9ee9a72f
5
+ SHA512:
6
+ metadata.gz: 60edce6ad7801d418943af609c9bef4b09cc5ffeec88acca6ea9e111030f2f9981981c4b26f862d2b013dd260573ea2096e1df890803a03b07ffc6546fefc14e
7
+ data.tar.gz: 21aca11008af8b4ed59fdb5adaf366cf9bdbc7e66db7cee4582879cf64411f44f9faf54658c5e143fc8dd5db5eed7ffa8c6a1d013b795927e5fbd927c80c794b
data/CHANGELOG.md ADDED
@@ -0,0 +1,182 @@
1
+ Changelog
2
+ =============
3
+
4
+ 1.0.0
5
+ -----
6
+ - Added Contaiment validator
7
+ - Lots of other stuff
8
+
9
+ 0.6.8
10
+
11
+ - Lax restriction on ActiveSupport version
12
+
13
+ 0.6.7
14
+
15
+ - Rebuild with Ruby 1.8
16
+
17
+ 0.6.6
18
+
19
+ - Bump supported CouchPotato version
20
+
21
+ 0.6.5
22
+
23
+ - Retry on connection refused errors, useful when CouchDB takes a break in excessive test runs that teardown/re-create many databases
24
+
25
+ 0.6.4
26
+
27
+ - Restore Ruby 1.9.2 compatibility
28
+
29
+ 0.6.3
30
+
31
+ - Compatible with CouchPotato 0.5.6
32
+
33
+ 0.6.2
34
+
35
+ - Decorate conflict exceptions with information about the conflict
36
+
37
+ 0.6.1
38
+
39
+ - Fix warning of dynamically created views to point to the correct called
40
+
41
+ 0.6.0
42
+
43
+ - Ruby 1.9.2 compatible
44
+
45
+ - compatible with CouchPotato > 0.5 where the attributes are lazy loaded
46
+
47
+ - Depends on ActiveSupport/ActiveModel 3.x
48
+ --> Does not longer work with Rails 2.x !
49
+
50
+ 0.5.4
51
+
52
+ - Add Rake task to compact all views in a given database:
53
+ DATABASE=http://localhost:5984/my_db rake simply_couch:compact_design_documents
54
+
55
+ 0.5.3
56
+
57
+ - Change implementation of all_documents_without_deleted view so that it can now be passed view parameters
58
+
59
+ 0.5.1
60
+
61
+ - Fix nullifying soft deleted objects when they are not deleted
62
+
63
+ 0.5.0
64
+
65
+ - Add support for has_and_belongs_to_many relations:
66
+
67
+ n:m relations where the IDs are stored on one part as an array:
68
+
69
+ class Server
70
+ include SimplyCouch::Couch
71
+
72
+ property :hostname
73
+
74
+ has_and_belongs_to_many :networks, :storing_keys => true
75
+ end
76
+
77
+ class Network
78
+ include SimplyCouch::Couch
79
+
80
+ property :klass
81
+
82
+ has_and_belongs_to_many :servers, :storing_keys => false
83
+ end
84
+
85
+ network = Network.create(:klass => "A")
86
+ server = Server.new(:hostname => 'www.example.com')
87
+ network.add_server(server)
88
+ server.network_ids # => [network.id]
89
+ network.servers # => [server]
90
+ server.networks # => [network]
91
+
92
+ The array property holding the IDs of the other item will be used to constuct two view to lookup
93
+ the other part. Soft deleting is only supported on the class holding the IDs.
94
+
95
+ - Add support for .last - which is the same as first by reverse order
96
+
97
+ User.last # => User.find(:first, :order => :desc)
98
+
99
+ - Drop support for SimpleDB
100
+
101
+ 0.3.8
102
+
103
+ - Fix loading of has_many/has_one associations for inherited relations.
104
+
105
+ - Pre-populate the parent object on has_many and has_one associations so that user.posts.first.user
106
+ doesn't reload the user.
107
+
108
+ - Add support for associations not named after the class [akm]
109
+
110
+ 0.3.3
111
+
112
+ - Fix association counting bug
113
+
114
+ - Introduce :ignore option to has_many :dependent option. If :dependent is set to :ignore,
115
+ dependent objects will not be deleted or nullified but just ignored.
116
+
117
+ 0.3.0
118
+ =============
119
+
120
+ - SimplyCouch now automatically retries conflicted save operations if it is possible to resolve the conflict.
121
+ Solving the conflict means that if updated were done one different attributes the local object will
122
+ refresh those attributes and try to save again. This will be tried two times by default. Afterwards the conflict
123
+ exception will be re-raised.
124
+
125
+ This feature can be controlled on the class level like this: User.auto_conflict_resolution_on_save = true | false
126
+
127
+ 0.2.5
128
+ =============
129
+
130
+ - Allow to pass a custom logger to S3-attachments / RightAws
131
+
132
+ - Support :order option to has_many associations and classes, e.g:
133
+
134
+ @user.posts(:order => :desc)
135
+ Post.find(:all, :order => :desc)
136
+
137
+ Default to the CouchDB default of ascending.
138
+ Please update ALL design documents!
139
+
140
+
141
+ - Support :limit option to has_many and has_many :through associations, e.g:
142
+
143
+ @user.posts(:limit => 5)
144
+
145
+ 0.1.14
146
+ =============
147
+
148
+ - Add ability to delete all design documents:
149
+
150
+ SimplyCouch::Couch.delete_all_design_documents('http://localhost:5984/mydbname')
151
+
152
+ - Add rake tasks to delete all design documents. In your Rakefile:
153
+
154
+ require 'simply_couch/rake'
155
+
156
+ Then you can delete all design documents in a database like this:
157
+
158
+ DATABASE=http://localhost:5984/mydb rake simply_couch:delete_design_documents
159
+
160
+ 0.1.13
161
+ =============
162
+
163
+ - Please delete all your design documents!
164
+ - Auto-generate count-methods for has_many associations, e.g
165
+
166
+ class Blog
167
+ include SimplyCouch::Couch
168
+ has_many :posts
169
+ end
170
+
171
+ class Post
172
+ include SimplyCouch::Couch
173
+ belongs_to :blog
174
+ end
175
+
176
+ blog = Blog.create
177
+ blog.post_count
178
+ # => 0
179
+
180
+ Post.create(:blog => blog)
181
+ blog.post_count(:force_reload => true)
182
+ # => 1
data/LICENSE.txt ADDED
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright (c) 2010 Peritor GmbH <info@peritor.com>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
data/README.md ADDED
@@ -0,0 +1,294 @@
1
+ # SimplyCouch
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/simply_couch.svg)](https://rubygems.org/gems/simply_couch)
4
+ [![License](https://img.shields.io/badge/license-BSD--2--Clause-blue.svg)](LICENSE.txt)
5
+
6
+ **Simple CouchDB ORM for Rails** — ActiveModel-compliant, driver-agnostic.
7
+
8
+ Zero driver dependencies. Your app brings its own CouchDB client (couchrest, couchbase, etc.).
9
+
10
+ ## History
11
+
12
+ SimplyCouch is based on **[simply_stored](https://github.com/peritor/simply_stored)** (140 ★), created by [Mathias Meyer](https://github.com/roidrage) and [Jonathan Weiss](https://github.com/jweiss) at [Peritor Consulting](https://github.com/peritor) in Berlin (~2010). simply_stored was a convenience layer on top of [CouchPotato](https://github.com/langalex/couch_potato).
13
+
14
+ This fork evolved over a decade with substantial additions — pagination, ancestry trees, embedded documents, include relations, multi-database support, and a migration toward ActiveModel. In 2026, the CouchPotato dependency was fully removed (~930 lines of view system + persistence ported directly into the gem), couchrest was removed from the gemspec, and the gem was renamed to **SimplyCouch** as its own project.
15
+
16
+ **Where are the original authors?** Jonathan Weiss (jweiss) co-founded Scalarium and is active in the Berlin tech scene. Mathias Meyer (roidrage) moved to Amazon Web Services Germany. Peritor's [webistrano](https://github.com/peritor/webistrano) (868 ★) was widely used in the Capistrano era.
17
+
18
+ ## Installation
19
+
20
+ ```ruby
21
+ gem 'simply_couch'
22
+ ```
23
+
24
+ Or from git:
25
+
26
+ ```ruby
27
+ gem 'simply_couch', git: 'https://github.com/bterkuile/simply_couch.git'
28
+ ```
29
+
30
+ You must also add a CouchDB client to your Gemfile (the gem doesn't force one):
31
+
32
+ ```ruby
33
+ gem 'couchrest' # or couchbase, or any CouchDB HTTP client
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ```ruby
39
+ class User
40
+ include SimplyCouch::Model
41
+
42
+ property :name
43
+ property :email
44
+ property :active, type: Boolean
45
+ property :last_login, type: Time
46
+ property :tags, type: Array
47
+
48
+ has_many :posts
49
+ belongs_to :company
50
+
51
+ view :by_name, key: :name
52
+ view :active_by_created, key: :created_at, conditions: 'doc.active == true'
53
+ end
54
+
55
+ class Post
56
+ include SimplyCouch::Model
57
+
58
+ property :title
59
+ property :body
60
+
61
+ belongs_to :user
62
+ end
63
+
64
+ # CRUD
65
+ user = User.create(name: 'Alice', email: 'alice@example.com', active: true)
66
+ user.update(name: 'Alice B.')
67
+ user.destroy
68
+
69
+ # Queries
70
+ User.find_by_name('Alice')
71
+ User.find_all_by_active(true)
72
+ User.active_by_created(descending: true)
73
+ User.all(page: 1, per_page: 40)
74
+
75
+ # Associations
76
+ user.posts # => [Post, ...]
77
+ user.posts(limit: 5, order: :desc)
78
+ user.post_count # => 42
79
+ ```
80
+
81
+ ## Features
82
+
83
+ ### Properties & Type Casting
84
+
85
+ ```ruby
86
+ property :name
87
+ property :age, type: Integer
88
+ property :price, type: Float
89
+ property :active, type: Boolean # stored as true/false
90
+ property :last_login, type: Time
91
+ property :tags, type: Array
92
+ property :metadata, type: Hash
93
+ ```
94
+
95
+ ### Associations
96
+
97
+ `belongs_to`, `has_many`, `has_many_embedded`, `has_and_belongs_to_many`, `has_one`, `embedded_in`.
98
+
99
+ ```ruby
100
+ class Post
101
+ include SimplyCouch::Model
102
+ has_many :comments, dependent: :destroy
103
+ has_many :authors, through: :comments, source: :user
104
+ belongs_to :category
105
+ end
106
+
107
+ class User
108
+ include SimplyCouch::Model
109
+ has_and_belongs_to_many :networks, storing_keys: true
110
+ end
111
+ ```
112
+
113
+ ### Validations
114
+
115
+ Standard ActiveModel validations plus a `containment` validator for array properties:
116
+
117
+ ```ruby
118
+ class Page
119
+ include SimplyCouch::Model
120
+ property :categories
121
+ validates_containment_of :categories, in: %w[news blog docs]
122
+ end
123
+ ```
124
+
125
+ ### Callbacks
126
+
127
+ `before_save`, `after_save`, `before_create`, `after_create`, `before_destroy`, `after_destroy` — all standard ActiveModel callbacks.
128
+
129
+ ### Views
130
+
131
+ CouchDB views are auto-generated from your model's property declarations. JavaScript only (Erlang dropped in 2026 port).
132
+
133
+ ```ruby
134
+ view :by_status, key: :status
135
+ view :published, key: :created_at, conditions: 'doc.status == "published"'
136
+ view :by_tags, key: :tags # array properties work too
137
+ ```
138
+
139
+ Custom views and raw map/reduce are supported via view spec classes.
140
+
141
+ ### Pagination
142
+
143
+ ```ruby
144
+ Post.all(page: 2, per_page: 25)
145
+ User.active_by_created(page: 1, per_page: 50, descending: true)
146
+ ```
147
+
148
+ ### Soft Delete
149
+
150
+ ```ruby
151
+ class Document
152
+ include SimplyCouch::Model
153
+ enable_soft_delete # defaults to :deleted_at
154
+ end
155
+
156
+ doc = Document.create(title: 'draft')
157
+ doc.destroy
158
+ Document.all # => [] (soft-deleted filtered out)
159
+ Document.all(with_deleted: true) # => [doc] (recoverable)
160
+ ```
161
+
162
+ ### Ancestry (Tree Structures)
163
+
164
+ ```ruby
165
+ class Page
166
+ include SimplyCouch::Model
167
+ property :title
168
+ has_ancestry
169
+ end
170
+
171
+ # Build trees
172
+ parent = Page.create(title: 'Products')
173
+ child = Page.create(title: 'Widgets', parent: parent)
174
+
175
+ # Query trees
176
+ Page.roots # pages with no parent
177
+ Page.full_tree # entire tree loaded in one query
178
+ parent.children # direct children
179
+ parent.descendants # all descendants (flattened)
180
+ child.ancestors # path to root
181
+
182
+ # Scoped trees (different trees per property)
183
+ has_ancestry by_property: :locale
184
+ ```
185
+
186
+ ### Dynamic Finders
187
+
188
+ ```ruby
189
+ User.find_by_name('Alice')
190
+ User.find_all_by_active(true)
191
+ User.count_by_active(true)
192
+ ```
193
+
194
+ ### Include Relations
195
+
196
+ Eager-load associations to avoid N+1 queries on CouchDB:
197
+
198
+ ```ruby
199
+ Post.all(include: :user) # loads users with posts
200
+ Post.all(include: [:user, :comments]) # multiple associations
201
+ ```
202
+
203
+ ### Conflict Resolution
204
+
205
+ Auto-merge on CouchDB conflicts by default (can be disabled):
206
+
207
+ ```ruby
208
+ User.auto_conflict_resolution_on_save = false # disable
209
+ ```
210
+
211
+ ### Multi-Database Support
212
+
213
+ ```ruby
214
+ class ArchivedPost
215
+ include SimplyCouch::Model
216
+ use_database 'http://couchdb:5984/archive'
217
+ end
218
+ ```
219
+
220
+ ### Design Document Splitting
221
+
222
+ Prevent full view reindexing when adding a new view:
223
+
224
+ ```ruby
225
+ class Post
226
+ include SimplyCouch::Model
227
+ split_design_documents_per_view # each view → own _design doc
228
+
229
+ view :by_user_id, key: :user_id # → _design/Post_view_by_user_id
230
+ view :by_status, key: :status # → _design/Post_view_by_status
231
+ end
232
+ ```
233
+
234
+ Without splitting, changing any view reindexes all views. On large databases, this can take hours.
235
+ With splitting, only the new/changed view reindexes.
236
+
237
+ ### Attachments
238
+
239
+ SimplyCouch supports **two** attachment strategies — use the one that fits your use case:
240
+
241
+ #### 1. CouchDB Native Inline Attachments
242
+
243
+ ```ruby
244
+ class Invoice
245
+ include SimplyCouch::Model
246
+ include SimplyCouch::Model::Attachments
247
+ end
248
+
249
+ invoice.put_attachment('receipt.pdf', file, content_type: 'application/pdf')
250
+ invoice.fetch_attachment('receipt.pdf')
251
+ invoice.delete_attachment('receipt.pdf')
252
+ invoice.attachment_names # => ['receipt.pdf', 'logo.png']
253
+ ```
254
+
255
+ Attachments are stored inline in the CouchDB document — atomic, no extra storage, replicable.
256
+
257
+ #### 2. ActiveStorage Compatibility
258
+
259
+ *Coming soon — `has_one_attached` / `has_many_attached` backed by CouchDB attachments.*
260
+
261
+ See `docs/attachments.md` for a detailed comparison of approaches.
262
+
263
+ ### Legacy: S3 Attachments
264
+
265
+ The `has_s3_attachment` method (using RightAws) exists but is **unmaintained and untested**.
266
+ It was part of the original simply_stored and has not been verified in years. Use CouchDB
267
+ native attachments or ActiveStorage instead.
268
+
269
+ ## Dependencies
270
+
271
+ | Gem | Version | Notes |
272
+ |-----|---------|-------|
273
+ | activemodel | >= 6.0 | Validations, callbacks, dirty tracking |
274
+ | activesupport | >= 6.0 | Inflections, callbacks, concern |
275
+
276
+ **No CouchDB driver dependency.** Add `couchrest` or `couchbase` to your app's Gemfile.
277
+
278
+ ## Testing
279
+
280
+ Uses RSpec with an in-memory CouchDB via [RockingChair](https://github.com/jweiss/rocking_chair).
281
+
282
+ ```bash
283
+ bundle exec rspec
284
+ ```
285
+
286
+ ## License
287
+
288
+ BSD 2-Clause — see [LICENSE.txt](LICENSE.txt)
289
+
290
+ ## Credits
291
+
292
+ - **Original simply_stored:** [Mathias Meyer](https://github.com/roidrage) & [Jonathan Weiss](https://github.com/jweiss) at [Peritor Consulting](https://github.com/peritor)
293
+ - **Fork & simply_couch:** [Benjamin ter Kuile](https://github.com/bterkuile)
294
+ - **CouchPotato removal + 2026 port:** BenClaw & Benjamin ter Kuile
@@ -0,0 +1,15 @@
1
+ # use ISO8601 as timeformat
2
+ class Date
3
+ def to_json(*a)
4
+ %|"#{as_json}"|
5
+ end
6
+
7
+ def as_json(*args)
8
+ iso8601
9
+ end
10
+
11
+ def self.json_create string
12
+ return nil if string.nil?
13
+ Date.parse(string)
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ require 'active_support/time'
2
+ # use ISO8601 as timeformat
3
+ class Time
4
+ def to_json(*a)
5
+ %|"#{as_json}"|
6
+ end
7
+
8
+ def as_json(*args)
9
+ getutc.iso8601
10
+ end
11
+
12
+ def self.json_create string
13
+ return nil if string.nil?
14
+ d = DateTime.parse(string.to_s).new_offset
15
+ self.utc(d.year, d.month, d.day, d.hour, d.min, d.sec).in_time_zone
16
+ end
17
+ end
18
+
19
+ ActiveSupport::TimeWithZone.class_eval do
20
+ def as_json(*args)
21
+ utc.iso8601
22
+ end
23
+ end
@@ -0,0 +1,72 @@
1
+ module SimplyCouch
2
+ module ClassMethods
3
+ module Base
4
+ def get_class_from_name(klass_name)
5
+ # Try to find class from property definition
6
+ if property = _find_property(klass_name) and property.respond_to?(:options) and property.options[:class_name].present?
7
+ property.options[:class_name].constantize
8
+ else # Fall back to name guessing
9
+ base = klass_name.to_s.gsub('__','/')
10
+ base = base.classify unless base[0,1] =~ /[A-Z]/
11
+ base.constantize
12
+ end
13
+ end
14
+
15
+ def foreign_key
16
+ name.underscore.gsub('/','__').gsub('::','__') + "_id"
17
+ end
18
+
19
+ def foreign_property
20
+ name.underscore.gsub('/','__').gsub('::','__')
21
+ end
22
+
23
+ def attr_protected(*args)
24
+ @_protected_attributes ||= []
25
+ @_protected_attributes += args.to_a
26
+ end
27
+
28
+ def attr_accessible(*args)
29
+ @_accessible_attributes ||= []
30
+ @_accessible_attributes += args.to_a
31
+ end
32
+
33
+ def _find_property(name)
34
+ properties.find{|property| property.name == name}
35
+ end
36
+
37
+ # Namespace aware method of creating proper class names
38
+ def find_association_class_name(association_name)
39
+ (name.split('::')[0..-2] + [association_name.to_s.singularize.camelize]).join('::')
40
+ end
41
+
42
+ # More compatibility with active record plugins
43
+ def primary_key
44
+ 'id'
45
+ end
46
+
47
+ def view(view_name, options)
48
+ options[:reduce] = options.delete(:reduce_function) if options[:reduce_function]
49
+ options[:map] = options.delete(:map_function) if options[:map_function]
50
+ super(view_name, options)
51
+ end
52
+
53
+ # Fix for paperclip > 3.5.2
54
+ def after_commit(*); end
55
+
56
+ # Get documents by ids and bulk update attributes
57
+ def bulk_update(ids, pairs)
58
+ # Bulk load documents
59
+ # Map to doc
60
+ # Filter out errors, or none founds (compact)
61
+ # Select the Couch objects
62
+ docs = database.couchrest_database.bulk_load(ids)['rows'].map{|r| r['doc']}.compact.select{|d| d.is_a?(SimplyCouch::Model)}
63
+ for doc in docs
64
+ pairs.each_pair do |k, v|
65
+ doc.send("#{k}=", v) if doc.respond_to?("#{k}=")
66
+ end
67
+ doc.save # Should become a bulk update in the future
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end