Module: LooseChange::Views

Included in:
Base
Defined in:
lib/loose_change/views.rb

Instance Method Summary collapse

Instance Method Details

#add_view(name, map, reduce = nil) ⇒ Object

Add a view to the this model’s design document on CouchDB. The view is identified by name, defined by map and optionally reduce, which are composed of JavaScript functions. For more information on CouchDB views, see wiki.apache.org/couchdb/Introduction_to_CouchDB_views



57
58
59
60
61
62
63
64
65
# File 'lib/loose_change/views.rb', line 57

def add_view(name, map, reduce = nil)
  design_doc = JSON.parse(RestClient.get("#{ self.database.uri }/_design/#{ CGI.escape(self.model_name) }"))
  current_views = design_doc['views'] || {}
  JSON.parse(RestClient.put("#{ self.database.uri }/_design/#{ CGI.escape(self.model_name) }",
                            { '_id' => design_doc['_id'],
                              '_rev' => design_doc['_rev'],
                              'language' => 'javascript',
                              'views' => current_views.merge({name => {'map' => map, 'reduce' => reduce}})}.to_json, default_headers))
end

#all(opts = {}) ⇒ Object

Retrieve all of this model’s documents currently stored on CouchDB.



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

def all(opts = {})
  view(:all, opts.merge!(:include_docs => true))
end

#doc_key(key) ⇒ Object

:nodoc:



94
95
96
# File 'lib/loose_change/views.rb', line 94

def doc_key(key)
  "doc['#{ key }']"
end

#existence_check(key) ⇒ Object

:nodoc:



80
81
82
# File 'lib/loose_change/views.rb', line 80

def existence_check(key)
  "(#{ doc_key(key) } != null)"
end

#key_for(keys) ⇒ Object

:nodoc:



85
86
87
88
89
90
91
# File 'lib/loose_change/views.rb', line 85

def key_for(keys)
  if keys.length == 1
    doc_key(keys.first)
  else
    "[#{keys.map {|k| doc_key(k) }.join(',')}]"
  end
end

#view(view_name, opts = {}) ⇒ Object

Invoke a view identified by view_name on this Loose Change model’s design document on CouchDB. Options specified in the opts hash will be passed along to CouchDB; for options see wiki.apache.org/couchdb/Introduction_to_CouchDB_views



10
11
12
13
14
15
16
# File 'lib/loose_change/views.rb', line 10

def view(view_name, opts = {})
  opts[:key] = opts.has_key?(:key) ? CGI.escape(opts[:key].to_json) : nil
  param_string = opts.reject {|k,v| v.nil?}.map {|k,v| "#{k}=#{v}"}.join('&')
  JSON.parse(RestClient.get("#{ self.database.uri }/_design/#{ CGI.escape(self.model_name) }/_view/#{ view_name }?#{ param_string }", default_headers))['rows'].map do |row|
    opts[:include_docs] ? instantiate_from_hash(row['doc']) : row['value']
  end
end

#view_by(*keys) ⇒ Object

Set up a view that will allow you to query CouchDB by keys. A view will be added to the design document on CouchDB, and a method to retrieve documents will be added to the Loose Change model class.

class Recipe < LooseChange::Base
  property :name
  property :popularity
  view_by :name
  view_by :name, :popularity
end

Recipe.by_name("lasagne")
Recipe.by_name_and_popularity("lasagne", 4)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/loose_change/views.rb', line 32

def view_by(*keys)
  view_name = "by_#{ keys.join('_and_') }"
  view_code = "function(doc) {
                 if ((doc['model_name'] == '#{ model_name }') && #{ keys.map {|k| existence_check k}.join('&&') }) {
                   emit(#{ key_for(keys) }, null)
                 }
               }
               "
  add_view(view_name, view_code)
  self.class.send(:define_method, view_name.to_sym) do |*keys|
    keys = keys.first if keys.length == 1
    view(view_name, :key => keys, :include_docs => true)
  end
end

#view_by_allObject

:nodoc:



68
69
70
71
72
73
74
75
76
77
# File 'lib/loose_change/views.rb', line 68

def view_by_all
  view_name = "all"
  view_code = "function(doc) {
                 if (doc['model_name'] == '#{ model_name }') {
                   emit(null);
                 }
               }
               "
  add_view(view_name, view_code)
end