Module: RelaxDB
- Defined in:
- lib/relaxdb.rb,
lib/more/grapher.rb,
lib/relaxdb/query.rb,
lib/relaxdb/views.rb,
lib/relaxdb/server.rb,
lib/relaxdb/relaxdb.rb,
lib/relaxdb/document.rb,
lib/relaxdb/migration.rb,
lib/relaxdb/paginator.rb,
lib/relaxdb/design_doc.rb,
lib/relaxdb/validators.rb,
lib/relaxdb/view_object.rb,
lib/relaxdb/view_result.rb,
lib/relaxdb/all_delegator.rb,
lib/relaxdb/view_uploader.rb,
lib/relaxdb/uuid_generator.rb,
lib/relaxdb/net_http_server.rb,
lib/relaxdb/paginate_params.rb,
lib/relaxdb/references_proxy.rb,
lib/relaxdb/taf2_curb_server.rb,
lib/relaxdb/view_by_delegator.rb
Defined Under Namespace
Modules: Validators
Classes: AllDelegator, CouchDB, DesignDocument, Document, DocumentNotSaved, GraphCreator, HTTP_404, HTTP_409, HTTP_412, Migration, MigrationVersion, NotFound, PaginateParams, Paginator, Query, ReferencesProxy, Server, UpdateConflict, UuidGenerator, ValidationFailure, View, ViewByDelegator, ViewCreator, ViewObject, ViewResult, ViewUploader
Constant Summary
collapse
- @@db =
nil
Class Method Summary
collapse
-
.bulk_save(*objs) ⇒ Object
-
.bulk_save!(*objs) ⇒ Object
-
.configure(config) ⇒ Object
-
.create_from_hash(data) ⇒ Object
-
.create_obj_from_doc(data) ⇒ Object
-
.create_object(data) ⇒ Object
-
.create_views? ⇒ Boolean
Set in configuration and consulted by view_docs_by, has_many, has_one, references_many and all Views will be added to CouchDB iff this is true.
-
.db ⇒ Object
-
.db_exists?(name) ⇒ Boolean
-
.db_info ⇒ Object
-
.dd ⇒ Object
This is a temporary method that helps the transition as RelaxDB moves to a single design doc per application.
-
.delete_db(name) ⇒ Object
-
.doc_ids(view_name, params) ⇒ Object
-
.docs(view_name, params) ⇒ Object
Queries a view that doesn’t emit the underlying doc as a val.
-
.enable_view_creation(default = true) ⇒ Object
-
.get(uri = nil) ⇒ Object
Convenience methods - should be in a diffent module?.
-
.ids_from_view(raw_result) ⇒ Object
-
.list_dbs ⇒ Object
-
.load(ids, atts = {}) ⇒ Object
Examples: RelaxDB.load “foo”, :conflicts => true RelaxDB.load “foo”, :revs => true RelaxDB.load [“foo”, “bar”].
-
.load!(ids) ⇒ Object
-
.logger ⇒ Object
-
.merge(data, merge_key) ⇒ Object
Should be invoked on the result of a join view Merges all rows based on merge_key and returns an array of ViewOject.
-
.paginate_view(view_name, atts) ⇒ Object
-
.pp_get(uri = nil) ⇒ Object
-
.pp_post(uri = nil, json = nil) ⇒ Object
-
.qpaginate_docs(view_name, atts) ⇒ Object
Paginates over views that don’t emit the underlying doc as a val using the same idiom as qpaginate_view.
-
.qpaginate_view(view_name, atts) ⇒ Object
The paginate_view method only populates next and prev links if they exist.
-
.reduce_result(data) ⇒ Object
-
.reload(obj) ⇒ Object
-
.replicate_db(source, target) ⇒ Object
-
.rf_view(view_name, params) ⇒ Object
CouchDB defaults reduce to true when a reduce func is present.
-
.use_db(name) ⇒ Object
Creates the named database if it doesn’t already exist.
-
.view(view_name, params = {}) ⇒ Object
Class Method Details
.bulk_save(*objs) ⇒ Object
103
104
105
106
107
108
109
|
# File 'lib/relaxdb/relaxdb.rb', line 103
def bulk_save(*objs)
begin
bulk_save!(*objs)
rescue ValidationFailure, UpdateConflict
false
end
end
|
.bulk_save!(*objs) ⇒ Object
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/relaxdb/relaxdb.rb', line 70
def bulk_save!(*objs)
if objs[0].equal? :all_or_nothing
objs.shift
all_or_nothing = true
end
pre_save_success = objs.inject(true) { |s, o| s &= o.pre_save }
raise ValidationFailure, objs.inspect unless pre_save_success
docs = {}
objs.each { |o| docs[o._id] = o }
data = { "docs" => objs }
data[:all_or_nothing] = true if all_or_nothing
resp = db.post("_bulk_docs", data.to_json )
data = JSON.parse(resp.body)
conflicted = []
data.each do |new_rev|
obj = docs[ new_rev["id"] ]
if new_rev["rev"]
obj._rev = new_rev["rev"]
obj.post_save
else
conflicted << obj._id
obj.conflicted
end
end
raise UpdateConflict, conflicted.inspect unless conflicted.empty?
objs
end
|
12
13
14
15
16
17
|
# File 'lib/relaxdb/relaxdb.rb', line 12
def configure(config)
@@db = CouchDB.new config
raise "A design_doc must be provided" unless config[:design_doc]
@dd = config[:design_doc]
end
|
.create_from_hash(data) ⇒ Object
291
292
293
|
# File 'lib/relaxdb/relaxdb.rb', line 291
def create_from_hash(data)
data["rows"].map { |row| create_object(row["value"]) }
end
|
.create_obj_from_doc(data) ⇒ Object
306
307
308
309
310
|
# File 'lib/relaxdb/relaxdb.rb', line 306
def create_obj_from_doc(data)
klass = data["relaxdb_class"]
k = klass.split("::").inject(Object) { |x, y| x.const_get y }
k.new data
end
|
.create_object(data) ⇒ Object
295
296
297
298
299
300
301
302
303
304
|
# File 'lib/relaxdb/relaxdb.rb', line 295
def create_object(data)
klass = data.is_a?(Hash) && data["relaxdb_class"]
if klass
k = klass.split("::").inject(Object) { |x, y| x.const_get y }
k.new data
else
ViewObject.create data
end
end
|
.create_views? ⇒ Boolean
Set in configuration and consulted by view_docs_by, has_many, has_one, references_many and all Views will be added to CouchDB iff this is true
32
33
34
|
# File 'lib/relaxdb/relaxdb.rb', line 32
def create_views?
@create_views
end
|
.db ⇒ Object
36
37
38
|
# File 'lib/relaxdb/relaxdb.rb', line 36
def db
@@db
end
|
.db_exists?(name) ⇒ Boolean
49
50
51
|
# File 'lib/relaxdb/relaxdb.rb', line 49
def db_exists?(name)
db.db_exists? name
end
|
.db_info ⇒ Object
53
54
55
56
|
# File 'lib/relaxdb/relaxdb.rb', line 53
def db_info
data = JSON.parse db.get.body
create_object data
end
|
.dd ⇒ Object
This is a temporary method that helps the transition as RelaxDB moves to a single design doc per application.
21
22
23
|
# File 'lib/relaxdb/relaxdb.rb', line 21
def dd
@dd
end
|
.delete_db(name) ⇒ Object
58
59
60
|
# File 'lib/relaxdb/relaxdb.rb', line 58
def delete_db(name)
db.delete_db name
end
|
.doc_ids(view_name, params) ⇒ Object
162
163
164
165
166
|
# File 'lib/relaxdb/relaxdb.rb', line 162
def doc_ids view_name, params
params[:raw] = true
result = view view_name, params
ids_from_view result
end
|
.docs(view_name, params) ⇒ Object
Queries a view that doesn’t emit the underlying doc as a val.
155
156
157
158
159
160
|
# File 'lib/relaxdb/relaxdb.rb', line 155
def docs view_name, params
params[:raw] = true
params[:include_docs] = true
hash = view view_name, params
hash["rows"].map { |row| row["doc"] ? create_obj_from_doc(row["doc"]) : nil }
end
|
.enable_view_creation(default = true) ⇒ Object
25
26
27
28
|
# File 'lib/relaxdb/relaxdb.rb', line 25
def enable_view_creation default=true
View.reset
@create_views = default
end
|
.get(uri = nil) ⇒ Object
Convenience methods - should be in a diffent module?
314
315
316
|
# File 'lib/relaxdb/relaxdb.rb', line 314
def get(uri=nil)
JSON.parse(db.get(uri).body)
end
|
.ids_from_view(raw_result) ⇒ Object
168
169
170
|
# File 'lib/relaxdb/relaxdb.rb', line 168
def ids_from_view raw_result
raw_result["rows"].map { |h| h["id"] }
end
|
.list_dbs ⇒ Object
62
63
64
|
# File 'lib/relaxdb/relaxdb.rb', line 62
def list_dbs
db.list_dbs
end
|
.load(ids, atts = {}) ⇒ Object
Examples:
RelaxDB.load "foo", :conflicts => true
RelaxDB.load "foo", :revs => true
RelaxDB.load ["foo", "bar"]
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
# File 'lib/relaxdb/relaxdb.rb', line 121
def load(ids, atts={})
if ids.is_a? Array
return [] if ids.empty?
resp = db.post("_all_docs?include_docs=true", {:keys => ids}.to_json)
data = JSON.parse(resp.body)
data["rows"].map { |row| row["doc"] ? create_obj_from_doc(row["doc"]) : nil }
else
begin
qs = atts.map{ |k, v| "#{k}=#{v}" }.join("&")
qs = atts.empty? ? ids : "#{ids}?#{qs}"
resp = db.get qs
data = JSON.parse resp.body
create_obj_from_doc data
rescue HTTP_404
nil
end
end
end
|
.load!(ids) ⇒ Object
143
144
145
146
147
148
149
150
|
# File 'lib/relaxdb/relaxdb.rb', line 143
def load!(ids)
res = load(ids)
raise NotFound, ids if res == nil
raise NotFound, ids if res.respond_to?(:include?) && res.include?(nil)
res
end
|
.logger ⇒ Object
40
41
42
|
# File 'lib/relaxdb/relaxdb.rb', line 40
def logger
@@db.logger
end
|
.merge(data, merge_key) ⇒ Object
Should be invoked on the result of a join view Merges all rows based on merge_key and returns an array of ViewOject
202
203
204
205
206
207
208
209
210
211
|
# File 'lib/relaxdb/relaxdb.rb', line 202
def merge(data, merge_key)
merged = {}
data["rows"].each do |row|
value = row["value"]
merged[value[merge_key]] ||= {}
merged[value[merge_key]].merge!(value)
end
merged.values.map { |v| ViewObject.create(v) }
end
|
.paginate_view(view_name, atts) ⇒ Object
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
# File 'lib/relaxdb/relaxdb.rb', line 219
def paginate_view(view_name, atts)
page_params = atts.delete :page_params
view_keys = atts.delete :attributes
qpaginate = atts.delete :qpaginate
paginate_params = PaginateParams.new atts
raise paginate_params.error_msg if paginate_params.invalid?
paginator = Paginator.new(paginate_params, page_params)
atts[:reduce] = false
query = Query.new(view_name, atts)
query.merge(paginate_params)
docs = ViewResult.new(JSON.parse(db.get(query.view_path).body))
docs.reverse! if paginate_params.order_inverted?
if qpaginate
paginator.add_q_next_and_prev docs, view_name, view_keys
else
paginator.add_next_and_prev(docs, view_name, view_keys)
end
docs
end
|
.pp_get(uri = nil) ⇒ Object
318
319
320
321
|
# File 'lib/relaxdb/relaxdb.rb', line 318
def pp_get(uri=nil)
resp = db.get(uri)
pp(JSON.parse(resp.body))
end
|
.pp_post(uri = nil, json = nil) ⇒ Object
323
324
325
326
|
# File 'lib/relaxdb/relaxdb.rb', line 323
def pp_post(uri=nil, json=nil)
resp = db.post(uri, json)
pp(JSON.parse(resp.body))
end
|
.qpaginate_docs(view_name, atts) ⇒ Object
Paginates over views that don’t emit the underlying doc as a val using the same idiom as qpaginate_view
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
|
# File 'lib/relaxdb/relaxdb.rb', line 269
def qpaginate_docs view_name, atts
page_params = atts.delete :page_params
view_keys = atts.delete :attributes
paginate_params = PaginateParams.new atts
raise paginate_params.error_msg if paginate_params.invalid?
paginator = Paginator.new(paginate_params, page_params)
atts[:raw] = true
query = Query.new(view_name, atts)
query.merge(paginate_params)
result = JSON.parse(db.get(query.view_path).body)
doc_ids = ids_from_view result
doc_ids.reverse! if paginate_params.order_inverted?
docs = RelaxDB.load! doc_ids
paginator.add_q_next_and_prev docs, view_name, view_keys
docs
end
|
.qpaginate_view(view_name, atts) ⇒ Object
The paginate_view method only populates next and prev links if they exist. However, its implementation uses three queries to determine if the links should exist.
It may be possible to determine if the links should exist with just a single query (by using a 1 doc offset on either side of the docs to be displayed).
This method makes a small change to paginate_view, dispensing with knowledge of when to create prev and next links but only requiring a single query.
Indiscrimate display of prev links makes this method more suited to forward navigation only.
260
261
262
263
|
# File 'lib/relaxdb/relaxdb.rb', line 260
def qpaginate_view view_name, atts
atts[:qpaginate] = true
paginate_view view_name, atts
end
|
.reduce_result(data) ⇒ Object
213
214
215
216
217
|
# File 'lib/relaxdb/relaxdb.rb', line 213
def reduce_result(data)
res = create_from_hash data
res.size == 0 ? nil :
res.size == 1 ? res[0] : res
end
|
.reload(obj) ⇒ Object
111
112
113
|
# File 'lib/relaxdb/relaxdb.rb', line 111
def reload(obj)
load(obj._id)
end
|
.replicate_db(source, target) ⇒ Object
66
67
68
|
# File 'lib/relaxdb/relaxdb.rb', line 66
def replicate_db(source, target)
db.replicate_db source, target
end
|
.rf_view(view_name, params) ⇒ Object
CouchDB defaults reduce to true when a reduce func is present. RelaxDB used to indiscriminately set reduce=false, allowing clients to override if desired. However, as of CouchDB 0.10, such behaviour results in
{"error":"query_parse_error","reason":"Invalid URL parameter `reduce` for map view."}
View issues.apache.org/jira/browse/COUCHDB-383#action_12722350
This method is an internal workaround for this change to CouchDB and may be removed if a future change allows for a better solution e.g. map=true or a _map endpoint
183
184
185
186
|
# File 'lib/relaxdb/relaxdb.rb', line 183
def rf_view view_name, params
params[:reduce] = false
view view_name, params
end
|
.use_db(name) ⇒ Object
Creates the named database if it doesn’t already exist
45
46
47
|
# File 'lib/relaxdb/relaxdb.rb', line 45
def use_db(name)
db.use_db name
end
|
.view(view_name, params = {}) ⇒ Object
188
189
190
191
192
193
194
195
196
197
198
|
# File 'lib/relaxdb/relaxdb.rb', line 188
def view(view_name, params = {})
q = Query.new(view_name, params)
resp = q.keys ? db.post(q.view_path, q.keys) : db.get(q.view_path)
hash = JSON.parse(resp.body)
if q.raw then hash
elsif q.reduce then reduce_result hash
else ViewResult.new hash
end
end
|