Module: CouchCrumbs::Document::ClassMethods

Includes:
Query
Defined in:
lib/couch_crumbs/document.rb

Instance Method Summary collapse

Methods included from Query

#query_docs, #query_values

Instance Method Details

#all(opts = {}) ⇒ Object

Return an array of all documents of this type



306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/couch_crumbs/document.rb', line 306

def all(opts = {})
  # Add the #all method
  view = design_doc.views(:name => "all")

  query_docs("#{ view.uri }".downcase, opts).collect do |doc|          
    if doc["crumb_type"]
      get!(doc["_id"])
    else
      warn "skipping unknown document: #{ doc }"
      
      nil
    end
  end
end

#child_document(model, opts = {}) ⇒ Object

Like child_document :address



352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/couch_crumbs/document.rb', line 352

def child_document(model, opts = {})
  model = model.to_s.downcase
  
  property("#{ model }_child_id")
  
  begin
    child_class = eval(model.modulize)
  rescue
    require "#{ model.methodize }.rb"
    retry
  end
  
  self.class_eval do
    define_method(model.to_sym) do
      child_class.get!(raw["#{ model }_child_id"])
    end
  
    define_method("#{ model }=".to_sym) do |new_child|
      raise ArgumentError.new("parent documents must be saved before adding children") if new_document?
      
      raw["#{ model }_child_id"] = new_child.id 
    end
  end
  
  nil
end

#child_documents(model, opts = {}) ⇒ Object

Like has_many :projects



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/couch_crumbs/document.rb', line 381

def child_documents(model, opts = {})
  model = model.to_s.downcase
  
  begin
    child_class = eval(model.modulize)
  rescue
    require "#{ model.methodize }.rb"
    retry
  end
  
  # Add a view to the child class
  View.create!(child_class.design_doc, "#{ crumb_type }_parent_id", View.advanced_json(File.join(File.dirname(__FILE__), "json", "children.json"), :parent => self.crumb_type, :child => model))
  
  # Add a method to access the model's new view
  self.class_eval do
    define_method(English::Inflect.plural(model)) do
      query_docs(eval(model.modulize).views(:name => "#{ self.class.crumb_type }_parent_id").uri).collect do |doc|
        child_class.get!(doc["_id"])
      end
    end
    
    define_method("add_#{ model }") do |new_child|
      new_child.send("#{ self.class.crumb_type }_parent_id=", self.id)
      new_child.save!
    end
  end
  
  nil
end

#create!(opts = {}) {|document| ... } ⇒ Object

TODO:
  • add before_create and after_create callbacks

Create and save a new document

Yields:

  • (document)


274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/couch_crumbs/document.rb', line 274

def create!(opts = {})
  document = new(opts)
  
  yield document if block_given?
  
  document.before_create
  
  document.save!
  
  document.after_create
  
  document
end

#crumb_typeObject

TODO:

cache crumb_type on the including base class

Return the useful portion of module/class type



158
159
160
# File 'lib/couch_crumbs/document.rb', line 158

def crumb_type
  class_variable_get(:@@crumb_type)
end

#custom_view(opts = {}) ⇒ Object

Create an advanced view from a given :template

Raises:

  • (ArgumentError)


248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/couch_crumbs/document.rb', line 248

def custom_view(opts = {})
  raise ArgumentError.new("opts must contain a :name key") unless opts.has_key?(:name)
  raise ArgumentError.new("opts must contain a :template key") unless opts.has_key?(:template)
          
  view = View.create!(design_doc, opts[:name], View.advanced_json(opts[:template], opts))
          
  self.class.instance_eval do
    define_method("#{ opts[:name] }".to_sym) do
      if view.has_reduce?
        query_values(view.uri)
      else
        query_docs(view.uri, :descending => false).collect do |doc|
          if doc["crumb_type"]
            new(:hash => doc)
          else
            warn "skipping unknown document: #{ doc }"
          end
        end
      end
    end
  end
end

#databaseObject

Return the database to use for this class



164
165
166
# File 'lib/couch_crumbs/document.rb', line 164

def database
  class_variable_get(:@@database)
end

#design_docObject

Return the design doc for this class



210
211
212
# File 'lib/couch_crumbs/document.rb', line 210

def design_doc
  Design.get!(database, :name => crumb_type)
end

#doc_view(*args) ⇒ Object

Create a default view on a given property, returning documents



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/couch_crumbs/document.rb', line 222

def doc_view(*args)
  # Get the design doc for this document type
  design = design_doc
  
  # Create simple views for the named properties
  args.each do |prop|
    view = View.create!(design, prop.to_s, View.simple_json(crumb_type, prop))
              
    self.class.instance_eval do
      define_method("by_#{ prop }".to_sym) do |opts|
        query_docs(view.uri, {:descending => false}.merge(opts||{})).collect do |doc|
          if doc["crumb_type"]
            new(:hash => doc)
          else
            warn "skipping unknown document: #{ document }"
          end
        end
      end
    end
  end
  
  nil
end

#get!(id) ⇒ Object

Return a specific document given an exact id

Raises:

  • (ArgumentError)


290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/couch_crumbs/document.rb', line 290

def get!(id)
  raise ArgumentError.new("id must not be blank") if id.empty? or id.nil?
  
  json = RestClient.get(File.join(database.uri, id))

  result = JSON.parse(json)

  document = new(
    :json => json
  )

  document
end

#parent_document(model, opts = {}) ⇒ Object

Like parent_document :person



323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/couch_crumbs/document.rb', line 323

def parent_document(model, opts = {})
  model = model.to_s.downcase
  
  property("#{ model }_parent_id")
  
  begin
    parent_class = eval(model.modulize)
  rescue
    require "#{ model.methodize }.rb"
    retry
  end
          
  self.class_eval do
    define_method(model.to_sym) do
      parent_class.get!(raw["#{ model }_parent_id"])
    end
  
    define_method("#{ model }=".to_sym) do |new_parent|
      raise ArgumentError.new("parent documents must be saved before children") if new_parent.new_document?
  
      raw["#{ model }_parent_id"] = new_parent.id 
    end
  end
  
  nil
end

#propertiesObject

Return all named properties for this document type



177
178
179
# File 'lib/couch_crumbs/document.rb', line 177

def properties
  class_variable_get(:@@properties)
end

#property(name, opts = {}) ⇒ Object

Add a named property to a document type



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/couch_crumbs/document.rb', line 183

def property(name, opts = {})
  name = name.to_sym
  properties << name
          
  class_eval do
    # getter
    define_method(name) do
      raw[name.to_s]
    end
    # setter
    define_method("#{ name }=".to_sym) do |new_value|
      raw[name.to_s] = new_value
    end
  end
end

#timestamps!Object

TODO:
  • add :created_at as a read-only property

Append default timestamps as named properties



202
203
204
205
206
# File 'lib/couch_crumbs/document.rb', line 202

def timestamps!
  [:created_at, :updated_at].each do |name|
    property(name)
  end
end

#use_database(name) ⇒ Object

Set the database that documents of this type will use (will create a new database if name does not exist)



171
172
173
# File 'lib/couch_crumbs/document.rb', line 171

def use_database(name)
  class_variable_set(:@@database, Database.new(:name => name))
end

#views(opts = {}) ⇒ Object

Return an array of all views for this class



216
217
218
# File 'lib/couch_crumbs/document.rb', line 216

def views(opts = {})
  design_doc.views(opts)
end