-
Notifications
You must be signed in to change notification settings - Fork 21
/
writer.ex
121 lines (106 loc) · 4.01 KB
/
writer.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
defmodule Couchdb.Connector.Writer do
@moduledoc """
The Writer module provides functions to create and update documents in
the CouchDB database given by the database properties.
## Examples
db_props = %{protocol: "http", hostname: "localhost",database: "couchdb_connector_test", port: 5984}
%{database: "couchdb_connector_test", hostname: "localhost", port: 5984, protocol: "http"}
Couchdb.Connector.Storage.storage_up(db_props)
{:ok, "{\\"ok\\":true}\\n"}
Couchdb.Connector.Writer.create(db_props, "{\\"key\\": \\"value\\"}")
{:ok, "{\\"ok\\":true,\\"id\\":\\"7dd00...\\",\\"rev\\":\\"1-59414e7...\\"}\\n",
[{"Server", "CouchDB/1.6.1 (Erlang OTP/18)"},
{"Location", "http://localhost:5984/couchdb_connector_test/7dd00..."},
{"ETag", "\\"1-59414e7...\\""}, {"Date", "Mon, 21 Dec 2015 16:13:23 GMT"},
{"Content-Type", "text/plain; charset=utf-8"},
{"Content-Length", "95"}, {"Cache-Control", "must-revalidate"}]}
"""
alias Couchdb.Connector.Types
alias Couchdb.Connector.Headers
alias Couchdb.Connector.Reader
alias Couchdb.Connector.UrlHelper
alias Couchdb.Connector.ResponseHandler, as: Handler
@doc """
Create a new document with given json and given id.
Clients must make sure that the id has not been used for an existing document
in CouchDB.
Either provide a UUID or consider using create_generate in case uniqueness cannot
be guaranteed.
"""
@spec create(Types.db_properties, String.t, String.t)
:: {:ok, String.t, Types.headers} | {:error, String.t, Types.headers}
def create(db_props, json, id) do
db_props
|> UrlHelper.document_url(id)
|> do_create(json)
end
@doc """
Create a new document with given json and a CouchDB generated id.
Fetching the uuid from CouchDB does of course incur a performance penalty as
compared to providing one.
"""
@spec create_generate(Types.db_properties, String.t)
:: {:ok, String.t, Types.headers} | {:error, String.t, Types.headers}
def create_generate(db_props, json) do
{:ok, uuid_json} = Reader.fetch_uuid(db_props)
uuid = hd(Poison.decode!(uuid_json)["uuids"])
create(db_props, json, uuid)
end
defp do_create(url, json) do
response = HTTPoison.put!(url, json, [Headers.json_header])
Handler.handle_put(response, :include_headers)
end
@doc """
Update the given document that is stored under the given id.
"""
@spec update(Types.db_properties, String.t, String.t)
:: {:ok, String.t, Types.headers} | {:error, String.t, Types.headers}
def update(db_props, json, id) do
db_props
|> UrlHelper.document_url(id)
|> do_update(json)
end
@doc """
Update the given document.
Note that an _id field must be contained in the document.
A missing _id field will trigger a RuntimeError.
"""
@spec update(Types.db_properties, String.t)
:: {:ok, String.t, Types.headers} | {:error, String.t, Types.headers}
def update(db_props, json) do
{doc_map, id} = parse_and_extract_id(json)
case id do
{:ok, id} ->
db_props
|> UrlHelper.document_url(id)
|> do_update(Poison.encode!(doc_map))
:error ->
raise RuntimeError, message:
"the document to be updated must contain an \"_id\" field"
end
end
defp do_update(url, json) do
url
|> HTTPoison.put!(json, [Headers.json_header])
|> Handler.handle_put(:include_headers)
end
defp parse_and_extract_id(json) do
doc_map = Poison.Parser.parse!(json)
{doc_map, Map.fetch(doc_map, "_id")}
end
@doc """
Delete the document with the given id in the given revision.
An error will be returned in case the document does not exist or the
revision is wrong.
"""
@spec destroy(Types.db_properties, String.t, String.t)
:: {:ok, String.t} | {:error, String.t}
def destroy(db_props, id, rev) do
db_props
|> UrlHelper.document_url(id)
|> do_destroy(rev)
end
defp do_destroy(url, rev) do
Handler.handle_delete(HTTPoison.delete!(url <> "?rev=#{rev}"))
end
end