dpla-couchrest 1.2.1.pre.dpla

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +176 -0
  6. data/README.md +66 -0
  7. data/Rakefile +23 -0
  8. data/THANKS.md +21 -0
  9. data/VERSION +1 -0
  10. data/couchrest.gemspec +36 -0
  11. data/examples/word_count/markov +38 -0
  12. data/examples/word_count/views/books/chunked-map.js +3 -0
  13. data/examples/word_count/views/books/united-map.js +1 -0
  14. data/examples/word_count/views/markov/chain-map.js +6 -0
  15. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  16. data/examples/word_count/views/word_count/count-map.js +6 -0
  17. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  18. data/examples/word_count/word_count.rb +46 -0
  19. data/examples/word_count/word_count_query.rb +40 -0
  20. data/examples/word_count/word_count_views.rb +26 -0
  21. data/history.txt +214 -0
  22. data/init.rb +1 -0
  23. data/lib/couchrest.rb +146 -0
  24. data/lib/couchrest/attributes.rb +89 -0
  25. data/lib/couchrest/commands/generate.rb +71 -0
  26. data/lib/couchrest/commands/push.rb +103 -0
  27. data/lib/couchrest/database.rb +402 -0
  28. data/lib/couchrest/design.rb +91 -0
  29. data/lib/couchrest/document.rb +105 -0
  30. data/lib/couchrest/helper/attachments.rb +29 -0
  31. data/lib/couchrest/helper/pager.rb +103 -0
  32. data/lib/couchrest/helper/streamer.rb +60 -0
  33. data/lib/couchrest/helper/upgrade.rb +51 -0
  34. data/lib/couchrest/middlewares/logger.rb +263 -0
  35. data/lib/couchrest/monkeypatches.rb +25 -0
  36. data/lib/couchrest/rest_api.rb +166 -0
  37. data/lib/couchrest/server.rb +92 -0
  38. data/lib/couchrest/support/inheritable_attributes.rb +107 -0
  39. data/spec/.gitignore +1 -0
  40. data/spec/couchrest/couchrest_spec.rb +197 -0
  41. data/spec/couchrest/database_spec.rb +914 -0
  42. data/spec/couchrest/design_spec.rb +206 -0
  43. data/spec/couchrest/document_spec.rb +400 -0
  44. data/spec/couchrest/helpers/pager_spec.rb +115 -0
  45. data/spec/couchrest/helpers/streamer_spec.rb +134 -0
  46. data/spec/couchrest/rest_api_spec.rb +241 -0
  47. data/spec/couchrest/server_spec.rb +35 -0
  48. data/spec/fixtures/attachments/README +3 -0
  49. data/spec/fixtures/attachments/couchdb.png +0 -0
  50. data/spec/fixtures/attachments/test.html +11 -0
  51. data/spec/fixtures/views/lib.js +3 -0
  52. data/spec/fixtures/views/test_view/lib.js +3 -0
  53. data/spec/fixtures/views/test_view/only-map.js +4 -0
  54. data/spec/fixtures/views/test_view/test-map.js +3 -0
  55. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  56. data/spec/spec.opts +5 -0
  57. data/spec/spec_helper.rb +46 -0
  58. data/utils/remap.rb +27 -0
  59. data/utils/subset.rb +30 -0
  60. metadata +212 -0
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'couchrest'
3
+
4
+ couch = CouchRest.new("http://127.0.0.1:5984")
5
+ db = couch.database('word-count-example')
6
+
7
+ puts "Now that we've parsed all those books into CouchDB, the queries we can run are incredibly flexible."
8
+ puts "\nThe simplest query we can run is the total word count for all words in all documents:"
9
+ puts "this will take a few minutes the first time. if it times out, just rerun this script in a few few minutes."
10
+ puts db.view('word_count/words').inspect
11
+
12
+ puts "\nWe can also narrow the query down to just one word, across all documents. Here is the count for 'flight' in all three books:"
13
+
14
+ word = 'flight'
15
+ params = {
16
+ :startkey => [word],
17
+ :endkey => [word,{}]
18
+ }
19
+
20
+ puts db.view('word_count/words',params).inspect
21
+
22
+ puts "\nWe scope the query using startkey and endkey params to take advantage of CouchDB's collation ordering. Here are the params for the last query:"
23
+ puts params.inspect
24
+
25
+ puts "\nWe can also count words on a per-title basis."
26
+
27
+ title = 'da-vinci'
28
+ params = {
29
+ :key => [word, title]
30
+ }
31
+
32
+ puts db.view('word_count/words',params).inspect
33
+
34
+
35
+ puts "\nHere are the params for 'flight' in the da-vinci book:"
36
+ puts params.inspect
37
+ puts
38
+ puts 'The url looks like this:'
39
+ puts 'http://127.0.0.1:5984/word-count-example/_view/word_count/count?key=["flight","da-vinci"]'
40
+ puts "\nTry dropping that in your browser..."
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'couchrest'
3
+
4
+ couch = CouchRest.new("http://127.0.0.1:5984")
5
+ db = couch.database('word-count-example')
6
+
7
+ word_count = {
8
+ :map => 'function(doc){
9
+ var words = doc.text.split(/\W/);
10
+ words.forEach(function(word){
11
+ if (word.length > 0) emit([word,doc.title],1);
12
+ });
13
+ }',
14
+ :reduce => 'function(key,combine){
15
+ return sum(combine);
16
+ }'
17
+ }
18
+
19
+ db.delete_doc db.get("_design/word_count") rescue nil
20
+
21
+ db.save_doc({
22
+ "_id" => "_design/word_count",
23
+ :views => {
24
+ :words => word_count
25
+ }
26
+ })
data/history.txt ADDED
@@ -0,0 +1,214 @@
1
+ == 1.2.0 - 2013-05-25
2
+
3
+ * Changes
4
+ * Added clobal configuration option to decode JSON objects (@langalex)
5
+ * Changing specs to test parameters as apposed to CouchDB for replication and restart
6
+ * Spec updates (@tapajos)
7
+ * Spec typos (@frasertweedale, @m1foley)
8
+
9
+ == 1.1.3 - 2012-07-31
10
+
11
+ * Minor changes
12
+ * Add support for HTTP HEAD requests (Tim Anglade)
13
+ * Make CouchRest#database! check if a db exists before creating it (Tim Anglade)
14
+ * Use _doc suffix in examples for delete and save (Mickael Riga)
15
+ * Database#view should not modify the params (@krishan)
16
+ * Fix replication with couchdb >= 1.1.0 (@erickt)
17
+ * Streamer protection against bad responses improved (@erickt)
18
+ * Support atomic bulk save requests with all_or_nothing CouchDB parameter (@matthiasjakel)
19
+ * Update multi_json dependency so we can use any 1.x version (@dgraham)
20
+
21
+ == 1.1.2 - 2011-07-18
22
+
23
+ * Minor changes
24
+ * Added `as_couch_json` method. If available, will be called before sending document to JSON encoder.
25
+
26
+ == 1.1.1 - 2011-07-04
27
+
28
+ * Urgent change
29
+ * Ensuring attributes hash initalized on use to avoid issues when initializer is overwritten.
30
+
31
+ == 1.1.0 - 2011-06-25
32
+
33
+ * Minor changes
34
+ * Refactored basic CouchRest API (get, post, etc.) to pass-through RestClient and MultiJSON options, including headers.
35
+ * CouchRest::Attributes module created to make attribute related methods independent.
36
+
37
+ == 1.1.0.pre3 - 2011-06-06
38
+
39
+ * Major changes
40
+ * CouchRest::Response removed
41
+ * CouchRest::Document now forwards key Hash methods (instead of inheritance) (thanks @karmi for prompting the discussion: https://github.com/crx/tire/commit/abf491d0035843a0a7395c8c32b9b7c2120071f9)
42
+ * Support multiple JSON gems with multi_json (thanks chrisdurtschi)
43
+
44
+ == 1.1.0.pre2 - 2011-04-08
45
+
46
+ * Major changes
47
+ * Time#to_json monkey patch removed! Standard JSON methods now used instead.
48
+
49
+ * Minor alterations
50
+ * Named doc replication (thanks @ahamid)
51
+ * Database#update_doc no longer requires document to be returned from block (thanks @ferrous26)
52
+ * Streamer now available for all queries that return multiple documents (thanks @pcapr for pointer)
53
+ * Streamer#view method removed, use Database.view with block
54
+ * Database#changes method added (with streamer option)
55
+ * Added :allow_nil option when creating views
56
+ * Bug fix: only symbols can be passed as view options (helps fix auto :reduce option)
57
+
58
+ WARNING: If you depend on ordering by Time, this release may cause issues on old databases!
59
+ Either update your documents to use the new format (JSON standard), or use Javascript's Date.parse
60
+ method in your views. Also, use Time#utc to ensure universal ordering regardless of time
61
+ zone. (CouchRest Model does this automatically.)
62
+
63
+ == 1.0.2
64
+
65
+ * Minor enhancements
66
+ * Bundler
67
+ * Dependency versions upgrade
68
+ * Removed reduce option from view's defaults. Now detected according to presence of reduce function.
69
+ * Design#has_view? and Design#can_reduce_view? now available publically
70
+
71
+ == 1.0.1
72
+
73
+ * Minor enhancements
74
+ * rest-client version mismatch between couchrest.rb & gemspec
75
+ * json 1.4.X series re-enabled as tests now pass with v.1.4.6
76
+
77
+ == 1.0.0
78
+
79
+ * Major enhancements
80
+ * Moved ExtendedDocument and friends into own library, couchrest_extended_document. (Sam Lown)
81
+ * Removed HttpAbstraction component for direct interface with RestClient. (Sam Lown)
82
+ * Changed version to more conventional format starting from 1.0.0 to avoid ambiguity issues with order. (Sam Lown)
83
+
84
+ == 0.38
85
+
86
+ * Major enhancements
87
+ * Add create_target option to Database#replicate_to and #replicate_from. http://github.com/couchrest/couchrest/issues/#issue/26 (Alexander Uvarov)
88
+ * Removing unused core extensions and moving extlib_inhertiable_* methods to use couchrest_inheritable_*
89
+ to avoid conflicts with Rails. (Geoff Buesing)
90
+
91
+ * Minor enhancements
92
+ * Support for CouchDB 1.0
93
+ * Added Document#id= support (issue detected by Rory Franklin with RSpec model stubs)
94
+ * Fixing issues with CouchDB 1.0 and RestClient
95
+
96
+ == 0.37
97
+
98
+ * Minor enhancements
99
+ * Added gemspec (needed for Bundler install) (Tapajós)
100
+
101
+ == 0.36
102
+
103
+ * Major enhancements
104
+ * Adds support for continuous replication (sauy7)
105
+ * Automatic Type Casting (Alexander Uvarov, Sam Lown, Tim Heighes, Will Leinweber)
106
+ * Added a search method to CouchRest:Database to search the documents in a given database. (Dave Farkas, Arnaud Berthomier, John Wood)
107
+
108
+ * Minor enhancements
109
+ * Provide a description of the timeout error (John Wood)
110
+
111
+ == 0.35
112
+
113
+ * Major enhancements
114
+ * CouchRest::ExtendedDocument allow chaining the inherit class callback (Kenneth Kalmer) - http://github.com/couchrest/couchrest/issues#issue/8
115
+
116
+ * Minor enhancements
117
+ * Fix attachment bug (Johannes Jörg Schmidt)
118
+ * Fix create database exception bug (Damien Mathieu)
119
+ * Compatible with restclient >= 1.4.0 new responses (Julien Kirch)
120
+ * Bug fix: Attribute protection no longer strips attributes coming from the database (Will Leinweber)
121
+ * Bug fix: Remove double CGI escape when PUTting an attachment (nzoschke)
122
+ * Bug fix: Changing Class proxy to set database on result sets (Peter Gumeson)
123
+ * Bug fix: Updated time regexp (Nolan Darilek)
124
+ * Added an update_doc method to database to handle conflicts during atomic updates. (Pierre Larochelle)
125
+ * Bug fix: http://github.com/couchrest/couchrest/issues/#issue/2 (Luke Burton)
126
+
127
+ == 0.34
128
+
129
+ * Major enhancements
130
+
131
+ * Added support for https database URIs. (Mathias Meyer)
132
+ * Changing some validations to be compatible with activemodel. (Marcos Tapajós)
133
+ * Adds attribute protection to properties. (Will Leinweber)
134
+ * Improved CouchRest::Database#save_doc, added "batch" mode to significantly speed up saves at cost of lower durability gurantees. (Igal Koshevoy)
135
+ * Added CouchRest::Database#bulk_save_doc and #batch_save_doc as human-friendlier wrappers around #save_doc. (Igal Koshevoy)
136
+
137
+ * Minor enhancements
138
+
139
+ * Fix content_type handling for attachments
140
+ * Fixed a bug in the pagination code that caused it to paginate over records outside of the scope of the view parameters.(John Wood)
141
+ * Removed amount_pages calculation for the pagination collection, since it cannot be reliably calculated without a view.(John Wood)
142
+ * Bug fix: http://github.com/couchrest/couchrest/issues/#issue/2 (Luke Burton)
143
+ * Bug fix: http://github.com/couchrest/couchrest/issues/#issue/1 (Marcos Tapajós)
144
+ * Removed the Database class deprecation notices (Matt Aimonetti)
145
+ * Adding support to :cast_as => 'Date'. (Marcos Tapajós)
146
+ * Improve documentation (Marcos Tapajós)
147
+ * Streamer fixes (Julien Sanchez)
148
+ * Fix Save on Document & ExtendedDocument crashed if bulk (Julien Sanchez)
149
+ * Fix Initialization of ExtendentDocument model shouldn't failed on a nil value in argument (deepj)
150
+ * Change to use Jeweler and Gemcutter (Marcos Tapajós)
151
+
152
+ == 0.33
153
+
154
+ * Major enhancements
155
+
156
+ * Added a new Rack logger middleware letting you log/save requests/queries (Matt Aimonetti)
157
+
158
+ * Minor enhancements
159
+
160
+ * Added #amount_pages to a paginated result array (Matt Aimonetti)
161
+ * Ruby 1.9.2 compatible (Matt Aimonetti)
162
+ * Added a property? method for property cast as :boolean (John Wood)
163
+ * Added an option to force the deletion of a attachments (bypass 409s) (Matt Aimonetti)
164
+ * Created a new abstraction layer for the REST API (Matt Aimonetti)
165
+ * Bug fix: made ExtendedDocument#all compatible with Couch 0.10 (tc)
166
+
167
+ == 0.32
168
+
169
+ * Major enhancements
170
+
171
+ * ExtendedDocument.get doesn't raise an exception anymore. If no documents are found nil is returned.
172
+ * ExtendedDocument.get! works the say #get used to work and will raise an exception if a document isn't found.
173
+
174
+ * Minor enhancements
175
+
176
+ * Bug fix: Model.all(:keys => [1,2]) was not working (Matt Aimonetti)
177
+ * Added ValidationErrors#count in order to play nicely with Rails (Peter Wagenet)
178
+ * Bug fix: class proxy design doc refresh (Daniel Kirsh)
179
+ * Bug fix: the count method on the proxy collection was missing (Daniel Kirsch)
180
+ * Added #amount_pages to a paginated collection. (Matt Aimonetti)
181
+
182
+ == 0.31
183
+
184
+ * Major enhancements
185
+
186
+ * Created an abstraction HTTP layer to support different http adapters (Matt Aimonetti)
187
+ * Added ExtendedDocument.create({}) and #create!({}) so you don't have to do Model.new.create (Matt Aimonetti)
188
+
189
+ * Minor enhancements
190
+
191
+ * Added an init.rb file for easy usage as a Rails plugin (Aaron Quint)
192
+ * Bug fix: pagination shouldn't die on empty results (Arnaud Berthomier)
193
+ * Optimized ExtendedDocument.count to run about 3x faster (Matt Aimonetti)
194
+ * Added Float casting (Ryan Felton & Matt Aimonetti)
195
+
196
+ == 0.30
197
+
198
+ * Major enhancements
199
+
200
+ * Added support for pagination (John Wood)
201
+ * Improved performance when initializing documents with timestamps (Matt Aimonetti)
202
+
203
+ * Minor enhancements
204
+
205
+ * Extended the API to retrieve an attachment URI (Matt Aimonetti)
206
+ * Bug fix: default value should be able to be set as false (Alexander Uvarov)
207
+ * Bug fix: validates_is_numeric should be able to properly validate a Float instance (Rob Kaufman)
208
+ * Bug fix: fixed the Timeout implementation (Seth Falcon)
209
+
210
+
211
+ ---
212
+
213
+ Unfortunately, before 0.30 we did not keep a track of the modifications made to CouchRest.
214
+ You can see the full commit history on GitHub: http://github.com/couchrest/couchrest/commits/master/
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__),'lib', 'couchrest.rb')
data/lib/couchrest.rb ADDED
@@ -0,0 +1,146 @@
1
+ # Copyright 2008 J. Chris Anderson
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'rest_client'
16
+ require 'multi_json'
17
+
18
+ # Not sure why this is required, so removed until a reason is found!
19
+ $:.unshift File.dirname(__FILE__) unless
20
+ $:.include?(File.dirname(__FILE__)) ||
21
+ $:.include?(File.expand_path(File.dirname(__FILE__)))
22
+
23
+ require 'couchrest/monkeypatches'
24
+ require 'couchrest/rest_api'
25
+ require 'couchrest/support/inheritable_attributes'
26
+
27
+ require 'forwardable'
28
+
29
+ # = CouchDB, close to the metal
30
+ module CouchRest
31
+ autoload :Attributes, 'couchrest/attributes'
32
+ autoload :Server, 'couchrest/server'
33
+ autoload :Database, 'couchrest/database'
34
+ autoload :Document, 'couchrest/document'
35
+ autoload :Design, 'couchrest/design'
36
+ autoload :Model, 'couchrest/model'
37
+ autoload :Pager, 'couchrest/helper/pager'
38
+ autoload :Streamer, 'couchrest/helper/streamer'
39
+ autoload :Attachments, 'couchrest/helper/attachments'
40
+ autoload :Upgrade, 'couchrest/helper/upgrade'
41
+
42
+ # we extend CouchRest with the RestAPI module which gives us acess to
43
+ # the get, post, put, delete and copy
44
+ CouchRest.extend(::CouchRest::RestAPI)
45
+
46
+ # The CouchRest module methods handle the basic JSON serialization
47
+ # and deserialization, as well as query parameters. The module also includes
48
+ # some helpers for tasks like instantiating a new Database or Server instance.
49
+ class << self
50
+
51
+ # todo, make this parse the url and instantiate a Server or Database instance
52
+ # depending on the specificity.
53
+ def new(*opts)
54
+ Server.new(*opts)
55
+ end
56
+
57
+ def parse url
58
+ case url
59
+ when /^(https?:\/\/)(.*)\/(.*)\/(.*)/
60
+ scheme = $1
61
+ host = $2
62
+ db = $3
63
+ docid = $4
64
+ when /^(https?:\/\/)(.*)\/(.*)/
65
+ scheme = $1
66
+ host = $2
67
+ db = $3
68
+ when /^(https?:\/\/)(.*)/
69
+ scheme = $1
70
+ host = $2
71
+ when /(.*)\/(.*)\/(.*)/
72
+ host = $1
73
+ db = $2
74
+ docid = $3
75
+ when /(.*)\/(.*)/
76
+ host = $1
77
+ db = $2
78
+ else
79
+ db = url
80
+ end
81
+
82
+ db = nil if db && db.empty?
83
+
84
+ {
85
+ :host => (scheme || "http://") + (host || "127.0.0.1:5984"),
86
+ :database => db,
87
+ :doc => docid
88
+ }
89
+ end
90
+
91
+ # set proxy to use
92
+ def proxy url
93
+ RestClient.proxy = url
94
+ end
95
+
96
+ # ensure that a database exists
97
+ # creates it if it isn't already there
98
+ # returns it after it's been created
99
+ def database! url
100
+ parsed = parse url
101
+ cr = CouchRest.new(parsed[:host])
102
+ cr.database!(parsed[:database])
103
+ end
104
+
105
+ def database url
106
+ parsed = parse url
107
+ cr = CouchRest.new(parsed[:host])
108
+ cr.database(parsed[:database])
109
+ end
110
+
111
+ def paramify_url url, params = {}
112
+ if params && !params.empty?
113
+ query = params.collect do |k,v|
114
+ v = MultiJson.encode(v) if %w{key startkey endkey}.include?(k.to_s)
115
+ "#{k}=#{CGI.escape(v.to_s)}"
116
+ end.join("&")
117
+ url = "#{url}?#{query}"
118
+ end
119
+ url
120
+ end
121
+
122
+ @@decode_json_objects = false
123
+
124
+ def decode_json_objects=(value)
125
+ @@decode_json_objects = value
126
+ end
127
+
128
+ # When set to true, CouchRest.get tries to decode the JSON returned
129
+ # from CouchDB into a Ruby object. Default: false.
130
+ def decode_json_objects
131
+ @@decode_json_objects
132
+ end
133
+ end # class << self
134
+ end
135
+ # For the sake of backwards compatability, generate a dummy ExtendedDocument class
136
+ # which should be replaced by real library: couchrest_extended_document.
137
+ #
138
+ # Added 2010-05-10 by Sam Lown. Please remove at some point in the future.
139
+ #
140
+ class CouchRest::ExtendedDocument < CouchRest::Document
141
+
142
+ def self.inherited(subclass)
143
+ raise "ExtendedDocument is no longer included in CouchRest base driver, see couchrest_extended_document gem"
144
+ end
145
+
146
+ end
@@ -0,0 +1,89 @@
1
+ #
2
+ # CouchRest::Attributes
3
+ #
4
+ # When included, provide the owner with an attributes hash and
5
+ # accessors that forward calls to it.
6
+ #
7
+ # Provides the basic functionality of Hash without actually being
8
+ # a Hash using Ruby's standard Forwardable module.
9
+ #
10
+ module CouchRest
11
+
12
+ module Attributes
13
+ extend Forwardable
14
+
15
+ # Initialize a new CouchRest Document and prepare
16
+ # a hidden attributes hash.
17
+ #
18
+ # When inherting a Document, it is essential that the
19
+ # super method is called before you own changes to ensure
20
+ # that the attributes hash has been initialized before
21
+ # you attempt to use it.
22
+ def initialize(attrs = nil)
23
+ attrs.each{|k,v| self[k] = v} unless attrs.nil?
24
+ end
25
+
26
+ # Hash equivilent methods to access the attributes
27
+ def_delegators :_attributes, :to_a, :==, :eql?, :keys, :values, :each,
28
+ :reject, :reject!, :empty?, :clear, :merge, :merge!,
29
+ :encode_json, :as_json, :to_json, :frozen?
30
+
31
+ def []=(key, value)
32
+ _attributes[key.to_s] = value
33
+ end
34
+ def [](key)
35
+ _attributes[key.to_s]
36
+ end
37
+ def has_key?(key)
38
+ _attributes.has_key?(key.to_s)
39
+ end
40
+ def delete(key)
41
+ _attributes.delete(key.to_s)
42
+ end
43
+ def dup
44
+ new = super
45
+ @_attributes = @_attributes.dup
46
+ new
47
+ end
48
+ def clone
49
+ new = super
50
+ @_attributes = @_attributes.dup
51
+ new
52
+ end
53
+ def to_hash
54
+ _attributes
55
+ end
56
+
57
+ # Provide JSON data hash that can be stored in the database.
58
+ # Will go through each attribute value and request the `as_couch_json` method
59
+ # on each if available, or return the value as-is.
60
+ def as_couch_json
61
+ _attributes.inject({}) {|h, (k,v)| h[k] = v.respond_to?(:as_couch_json) ? v.as_couch_json : v; h}
62
+ end
63
+
64
+ # Freeze the object's attributes instead of the actual document.
65
+ # This prevents further modifications to stored data, but does allow access
66
+ # to local variables useful for callbacks or cached data.
67
+ def freeze
68
+ _attributes.freeze; self
69
+ end
70
+
71
+ # Provide details of the current keys in the reponse. Based on ActiveRecord::Base.
72
+ def inspect
73
+ attributes_as_nice_string = self.keys.collect { |key|
74
+ "#{key}: #{self[key].inspect}"
75
+ }.compact.join(", ")
76
+ "#<#{self.class} #{attributes_as_nice_string}>"
77
+ end
78
+
79
+ protected
80
+
81
+ # Define accessor for _attributes hash that will instantiate the
82
+ # model if this has not already been done.
83
+ def _attributes
84
+ @_attributes ||= {}
85
+ end
86
+
87
+ end
88
+
89
+ end