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/has_one_proxy.rb,
lib/relaxdb/view_uploader.rb,
lib/relaxdb/has_many_proxy.rb,
lib/relaxdb/uuid_generator.rb,
lib/relaxdb/net_http_server.rb,
lib/relaxdb/paginate_params.rb,
lib/relaxdb/belongs_to_proxy.rb,
lib/relaxdb/taf2_curb_server.rb,
lib/relaxdb/references_many_proxy.rb

Defined Under Namespace

Modules: Validators Classes: AllDelegator, BelongsToProxy, CouchDB, DesignDocument, Document, DocumentNotSaved, GraphCreator, HTTP_404, HTTP_409, HTTP_412, HasManyProxy, HasOneProxy, Migration, MigrationVersion, NotFound, PaginateParams, Paginator, Query, ReferencesManyProxy, Server, UpdateConflict, UuidGenerator, ValidationFailure, View, ViewCreator, ViewObject, ViewResult, ViewUploader

Constant Summary collapse

@@db =
nil

Class Method Summary collapse

Class Method Details

.bulk_save(*objs) ⇒ Object



102
103
104
105
106
107
108
# File 'lib/relaxdb/relaxdb.rb', line 102

def bulk_save(*objs)
  begin
    bulk_save!(*objs)
  rescue ValidationFailure, UpdateConflict
    false
  end
end

.bulk_save!(*objs) ⇒ Object

Raises:



69
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
# File 'lib/relaxdb/relaxdb.rb', line 69

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

.configure(config) ⇒ Object



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



217
218
219
# File 'lib/relaxdb/relaxdb.rb', line 217

def create_from_hash(data)
  data["rows"].map { |row| create_object(row["value"]) }
end

.create_object(data) ⇒ Object



221
222
223
224
225
226
227
228
229
230
# File 'lib/relaxdb/relaxdb.rb', line 221

def create_object(data)
  klass = data.is_a?(Hash) && data.delete("relaxdb_class")
  if klass
    k = klass.split("::").inject(Object) { |x, y| x.const_get y }
    k.new data
  else 
    # data is a scalar or not of a known class
    ViewObject.create data
  end
end

.create_views?Boolean

Set in configuration and consulted by view_by, has_many, has_one, references_many and all Views will be added to CouchDB iff this is true

Returns:

  • (Boolean)


31
32
33
# File 'lib/relaxdb/relaxdb.rb', line 31

def create_views?
  @create_views
end

.dbObject



35
36
37
# File 'lib/relaxdb/relaxdb.rb', line 35

def db
  @@db
end

.db_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/relaxdb/relaxdb.rb', line 48

def db_exists?(name)
  db.db_exists? name
end

.db_infoObject



52
53
54
55
# File 'lib/relaxdb/relaxdb.rb', line 52

def db_info
  data = JSON.parse db.get.body
  create_object data
end

.ddObject

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



57
58
59
# File 'lib/relaxdb/relaxdb.rb', line 57

def delete_db(name)
  db.delete_db name
end

.enable_view_creation(default = true) ⇒ Object



25
26
27
# File 'lib/relaxdb/relaxdb.rb', line 25

def enable_view_creation default=true
  @create_views = default
end

.get(uri = nil) ⇒ Object

Convenience methods - should be in a diffent module?



234
235
236
# File 'lib/relaxdb/relaxdb.rb', line 234

def get(uri=nil)
  JSON.parse(db.get(uri).body)
end

.list_dbsObject



61
62
63
# File 'lib/relaxdb/relaxdb.rb', line 61

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"]


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/relaxdb/relaxdb.rb', line 120

def load(ids, atts={})
  # RelaxDB.logger.debug(caller.inject("#{db.name}/#{ids}\n") { |a, i| a += "#{i}\n" })
  
  if ids.is_a? Array
    resp = db.post("_all_docs?include_docs=true", {:keys => ids}.to_json)
    data = JSON.parse(resp.body)
    data["rows"].map { |row| row["doc"] ? create_object(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_object data
    rescue HTTP_404
      nil
    end
  end
end

.load!(ids) ⇒ Object

Raises:



140
141
142
143
144
145
146
147
# File 'lib/relaxdb/relaxdb.rb', line 140

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

.loggerObject



39
40
41
# File 'lib/relaxdb/relaxdb.rb', line 39

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



179
180
181
182
183
184
185
186
187
188
# File 'lib/relaxdb/relaxdb.rb', line 179

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



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/relaxdb/relaxdb.rb', line 196

def paginate_view(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[: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?
  
  paginator.add_next_and_prev(docs, view_name, view_keys)
  
  docs
end

.pp_get(uri = nil) ⇒ Object



238
239
240
241
# File 'lib/relaxdb/relaxdb.rb', line 238

def pp_get(uri=nil)
  resp = db.get(uri)
  pp(JSON.parse(resp.body))
end

.pp_post(uri = nil, json = nil) ⇒ Object



243
244
245
246
# File 'lib/relaxdb/relaxdb.rb', line 243

def pp_post(uri=nil, json=nil)
  resp = db.post(uri, json)
  pp(JSON.parse(resp.body))
end

.reduce_result(data) ⇒ Object



190
191
192
193
194
# File 'lib/relaxdb/relaxdb.rb', line 190

def reduce_result(data)
  res = create_from_hash data
  res.size == 0 ? nil :
    res.size == 1 ? res[0] : res
end

.reload(obj) ⇒ Object



110
111
112
# File 'lib/relaxdb/relaxdb.rb', line 110

def reload(obj)
  load(obj._id)
end

.replicate_db(source, target) ⇒ Object



65
66
67
# File 'lib/relaxdb/relaxdb.rb', line 65

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



160
161
162
163
# File 'lib/relaxdb/relaxdb.rb', line 160

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



44
45
46
# File 'lib/relaxdb/relaxdb.rb', line 44

def use_db(name)
  db.use_db name
end

.view(view_name, params = {}) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
# File 'lib/relaxdb/relaxdb.rb', line 165

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