Class: Tatami::Couch

Inherits:
Object
  • Object
show all
Defined in:
lib/tatami/couch.rb

Defined Under Namespace

Classes: App, BulkImport, View

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db, url = 'http://localhost:5984', opts = {}) ⇒ Couch

Returns a new instance of Couch.

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :log (Boolean)
  • :db (String)


27
28
29
30
# File 'lib/tatami/couch.rb', line 27

def initialize db, url='http://localhost:5984', opts={}
  @env = opts.delete(:env)
  @db, @url, @opts = db, url, opts
end

Instance Attribute Details

#dbObject (readonly)

Returns the value of attribute db.



20
21
22
# File 'lib/tatami/couch.rb', line 20

def db
  @db
end

Instance Method Details

#blank!Object

delete and recreate the database



14
15
16
17
18
# File 'lib/tatami/couch.rb', line 14

def blank!
  conn.delete "/#{db_env}"
  conn.put "/#{db_env}"
  self
end

#bulk_import(limit = 100, &b) ⇒ Object



209
210
211
# File 'lib/tatami/couch.rb', line 209

def bulk_import limit=100, &b
  BulkImport.new self, limit, &b
end

#cast_response(data, format) ⇒ Object



38
39
40
41
42
43
44
45
46
47
# File 'lib/tatami/couch.rb', line 38

def cast_response data, format
  case format
  when :string
    data
  when :object
    JSON.parse(data)
  else
    Map.new JSON.parse(data)
  end
end

#connObject



6
7
8
9
10
11
12
# File 'lib/tatami/couch.rb', line 6

def conn
  @conn ||= Faraday.new(:url => @url) do |faraday|
    faraday.request  :url_encoded             # form-encode POST params
    faraday.response :logger                  if @opts[:log]
    faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
  end
end

#db_envObject



21
22
23
# File 'lib/tatami/couch.rb', line 21

def db_env()
  @env ? "#{@db}_#{@env}" : @db
end

#db_infoObject



74
# File 'lib/tatami/couch.rb', line 74

def db_info() get_db "" end

#design_new(type, name, content) ⇒ Object

creates new type in _design/ document

Parameters:

  • type (Symbol)

    :view, :list, :show



173
174
175
176
177
# File 'lib/tatami/couch.rb', line 173

def design_new type, name, content
  doc_merge_cached "_design/#{db_env}", :language => 'coffeescript',
                                     "#{type}s" =>
                                        { name => content }
end

#doc(id) ⇒ Object

_id 0c8e32db863b87c9f6233d5728545922 _rev 1-08c111cb2ccfbf117ed931bef444f730 error: not_found reason: missing name Frank GET /db/doc



142
143
144
145
# File 'lib/tatami/couch.rb', line 142

def doc id
  r = get_db "/#{id}"
  r[:error] == "not_found" ? nil : r
end

#doc_attach_app(id, file_root) ⇒ Object

Parameters:

  • file_root (String)


113
114
115
116
117
# File 'lib/tatami/couch.rb', line 113

def doc_attach_app id, file_root
  # curl -X PUT -v http://127.0.0.1:5984/cars/flot/index.html --data-binary "@test/fixtures/index.html" --header "Accept: text/html" --header "Transfer-Encoding: chunked" --header "Expect:"
  require 'tatami/app'
  put_db "/#{id}", "_attachments" => App.new.attachments(file_root)
end

#doc_create_or_update(id, attributes) ⇒ Object



119
120
121
122
123
124
125
# File 'lib/tatami/couch.rb', line 119

def doc_create_or_update id, attributes
  if old = doc(id)
    doc_update old, attributes
  else
    doc_new id, attributes
  end
end

#doc_merge(id, attributes) ⇒ Object



200
201
202
203
# File 'lib/tatami/couch.rb', line 200

def doc_merge id, attributes
  old = doc id
  doc_new old[:_id], old.combine(attributes)
end

#doc_merge_cached(id, attributes) ⇒ Object



161
162
163
164
165
166
167
168
169
# File 'lib/tatami/couch.rb', line 161

def doc_merge_cached id, attributes
  @cache ||= Map.new
  @cache[id] ||= begin
    doc(id) || Map.new
  end
  @cache.combine! id => attributes
  r = doc_new id, @cache[id]
  @cache[id][:_rev] = r[:rev]
end

#doc_new(id, attributes) ⇒ Doc

PUT /db/doc ok true id 0c8e32db863b87c9f6233d572854d6db rev 1-08c111cb2ccfbf117ed931bef444f730

Returns:

  • (Doc)


107
108
109
110
# File 'lib/tatami/couch.rb', line 107

def doc_new id, attributes
  id ||= next_id
  put_db "/#{id}", attributes
end

#doc_new_bulk(documents) ⇒ Object



205
206
207
# File 'lib/tatami/couch.rb', line 205

def doc_new_bulk documents
  post_db "/_bulk_docs", {:docs => documents}
end

#doc_update(old, new) ⇒ Object

Parameters:

  • old (Hash)
  • new (Hash)


156
157
158
159
# File 'lib/tatami/couch.rb', line 156

def doc_update old, new
  attributes = new.merge(:_rev => old[:_rev])
  doc_new old[:_id], attributes
end

#get(path, opts = {}) ⇒ Object



32
33
34
35
36
# File 'lib/tatami/couch.rb', line 32

def get path, opts={}
  puts "GET #{path}" if opts[:log]
  data = conn.get(path).body
  cast_response data, opts[:format]
end

#get_db(path, opts = {}) ⇒ Object



53
54
55
# File 'lib/tatami/couch.rb', line 53

def get_db path, opts={}
  get "/#{db_env}#{path}", opts
end

#get_db_string(path) ⇒ Object



49
50
51
# File 'lib/tatami/couch.rb', line 49

def get_db_string path
  conn.get("/#{db_env}#{path}").body
end

#load_design(pattern = "*") ⇒ Object

views name map views name reduce lists name



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

def load_design pattern="*"
  [ %w[erlang %% erl],
    %w[coffeescript # coffee]
  ].each do |language, comment, ext |
    Dir.glob("couches/#{@db}/#{pattern}.#{ext}").each do |path|
      source = IO.read(path)
      name = File.basename(path)[/[^\.]+/]
      map = Map.new(language: language)
      source.split(/^(?=#{comment} (?:views|lists) \S+)/m).each do |element|
        element.split("\n").first =~ /#{comment} (\S+) (\S+) ?(map|reduce)?/
        values = [$1,$2,$3].compact << element
        map.set *values
      end
      doc_create_or_update "_design/#{name}", map
    end
  end
end

#next_idString

Returns autogenerated available id (caches 10).

Returns:

  • (String)

    autogenerated available id (caches 10)



128
129
130
131
132
133
134
# File 'lib/tatami/couch.rb', line 128

def next_id
  @next_ids ||= []
  if @next_ids.empty?
    @next_ids = get("_uuids?count=10")[:uuids]
  end
  @next_ids.pop
end

#post_db(url, body, opts = {}) ⇒ Object



63
64
65
# File 'lib/tatami/couch.rb', line 63

def post_db url, body, opts={}
  verb :post, "/#{db_env}#{url}", body, opts
end

#post_db_string(url, body) ⇒ Object



69
70
71
# File 'lib/tatami/couch.rb', line 69

def post_db_string url, body
  conn.post("/#{db_env}#{url}", JSON.generate(body), 'Content-Type' => 'application/json').body
end

#put_db(url, body) ⇒ Object



67
# File 'lib/tatami/couch.rb', line 67

def put_db(url, body)  verb :put,  "/#{db_env}#{url}", body end

#show(name, doc = nil, design = db_env) ⇒ Object

GET /db/_design/design-doc/_show/show-name GET /db/_design/design-doc/_show/show-name/doc



149
150
151
152
# File 'lib/tatami/couch.rb', line 149

def show name, doc=nil, design=db_env
  d = doc ? "/#{doc}" : ""
  get_db_string "/_design/#{design}/_show/#{name}#{d}"
end

#verb(method, url, body, opts = {}) ⇒ Object



57
58
59
60
61
# File 'lib/tatami/couch.rb', line 57

def verb method, url, body, opts={}
  puts "#{method.upcase} #{url} #{body.inspect}" if opts[:log]
  resp = conn.send method, url, JSON.generate(body), 'Content-Type' => 'application/json'
  cast_response resp.body, opts[:format]
end

#versionObject



73
# File 'lib/tatami/couch.rb', line 73

def version() get('/')[:version] end

#view(name) ⇒ Object

GET /db/_design/design-doc/_view/view-name



232
233
234
235
# File 'lib/tatami/couch.rb', line 232

def view name
  @views ||= Map.new
  @views[name] ||= View.new self, name.to_s
end

#with_documents!(*docs) ⇒ Object



96
97
98
99
100
# File 'lib/tatami/couch.rb', line 96

def with_documents! *docs
  blank!
  load_design
  doc_new_bulk docs
end

#with_fixtures!(names, *docs) ⇒ Object

committed_update_seq: 0



87
88
89
90
91
92
93
94
# File 'lib/tatami/couch.rb', line 87

def with_fixtures! names, *docs
  blank!
  load_design
  documents = docs.map do |values|
    Hash[ names.zip(values) ]
  end
  doc_new_bulk documents
end