datomic-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ * Initial release that works with datomic 0.8.3488!
@@ -0,0 +1,22 @@
1
+ The MIT LICENSE
2
+
3
+ Copyright (c) 2012 Gabriel Horner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,55 @@
1
+ ## Description
2
+
3
+ This gem provides a simple way to use datomic's [http API](http://docs.datomic.com/rest.html).
4
+
5
+ ## Install
6
+
7
+ Install as a gem:
8
+
9
+ $ gem install datomic-client
10
+
11
+ If your application is using a Gemfile, add this to it:
12
+
13
+ gem 'datomic-client', :require => 'datomic/client'
14
+
15
+ and then `bundle`.
16
+
17
+ ## Usage
18
+
19
+ ```sh
20
+ # In another shell in datomic's directory
21
+ $ bin/rest 9000 socrates datomic:mem://
22
+
23
+ # In project's directory
24
+ $ irb -rdatomic/client
25
+ >> dbname = 'cosas'
26
+ >> datomic = Datomic::Client.new 'http://localhost:9000', 'socrates'
27
+ >> datomic.create_database(dbname)
28
+ >> datomic.database_info(dbname)
29
+ >> datomic.transact(dbname, "TODO")
30
+ >> datomic.datoms(dbname, 'aevt')
31
+ >> datomic.range(dbname, :a => "db/ident")
32
+ >> datomic.entity(1)
33
+ >> datomic.query("TODO")
34
+ >> datomic.monitor(dbname)
35
+ >> datomic.events(dbname) {|r| puts "Received: #{r.inspect}" }
36
+ ```
37
+
38
+ ## Issues
39
+ Please report them [on github](http://github.com/cldwalker/datomic-client/issues).
40
+
41
+ ## Contributing
42
+ [See here](http://tagaholic.me/contributing.html) for contribution policies.
43
+
44
+ ## Credits
45
+
46
+ * @flyingmachine for starting this with me
47
+
48
+ ##Todo
49
+
50
+ * Fix pending specs
51
+
52
+ ## Links
53
+
54
+ * [API documentation](http://docs.datomic.com/rest.html)
55
+ * [Initial announcement](http://blog.datomic.com/2012/09/rest-api.html)
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "datomic/client"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "datomic-client"
7
+ s.version = Datomic::Client::VERSION
8
+ s.homepage = "http://github.com/cldwalker/datomic-client"
9
+ s.authors = "Gabriel Horner"
10
+ s.email = "gabriel.horner@gmail.com"
11
+ s.homepage = "http://github.com/cldwalker/datomic-client"
12
+ s.summary = %q{http client for datomic's API}
13
+ s.description = "This gem provides a simple way to use datomic's http API - http://docs.datomic.com/rest.html."
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+
19
+ s.add_development_dependency 'bundler'
20
+ s.add_development_dependency 'rspec'
21
+ s.add_development_dependency 'rake', '~> 0.9.2.2'
22
+ s.add_dependency 'rest-client'
23
+ end
@@ -0,0 +1,62 @@
1
+ require 'rest-client'
2
+
3
+ module Datomic
4
+ class Client
5
+ VERSION = '0.1.0'
6
+
7
+ def initialize(url, storage = nil)
8
+ @url = url
9
+ @storage = storage
10
+ end
11
+
12
+ def create_database(dbname)
13
+ RestClient.put db_url(dbname), {}
14
+ end
15
+
16
+ def database_info(dbname)
17
+ RestClient.get db_url(dbname)
18
+ end
19
+
20
+ def transact(dbname, data)
21
+ RestClient.post db_url(dbname), data
22
+ end
23
+
24
+ def datoms(dbname, index, params = {})
25
+ RestClient.get db_url(dbname, "datoms/#{index}"), :params => params
26
+ end
27
+
28
+ def range(dbname, params = {})
29
+ RestClient.get db_url(dbname, 'range'), :params => params
30
+ end
31
+
32
+ def entity(dbname, id, params = {})
33
+ RestClient.get db_url(dbname, 'entity', id), :params => params
34
+ end
35
+
36
+ def query(query, params = {})
37
+ RestClient.get root_url("api/query"), :params => params.merge(:q => query)
38
+ end
39
+
40
+ def monitor(dbname)
41
+ RestClient.get root_url('monitor', @storage, dbname)
42
+ end
43
+
44
+ # Given block is called with Net::HTTPOK response from event
45
+ def events(dbname, &block)
46
+ RestClient::Request.execute(:method => :get,
47
+ :url => root_url('events', @storage, dbname),
48
+ :headers => {:accept => "text/event-stream"},
49
+ :block_response => block)
50
+ end
51
+
52
+ private
53
+
54
+ def root_url(*parts)
55
+ [@url].concat(parts).join('/')
56
+ end
57
+
58
+ def db_url(dbname, *parts)
59
+ root_url 'db', @storage, dbname, *parts
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,157 @@
1
+ require 'datomic/client'
2
+
3
+ describe Datomic::Client do
4
+ let(:datomic_uri) { ENV['DATOMIC_URI'] || 'http://localhost:9000' }
5
+ # datomic's `rest` needs to run for these tests to pass i.e.
6
+ # bin/rest 9000 socrates datomic:mem://
7
+ let(:client) do
8
+ Datomic::Client.new datomic_uri, ENV['DATOMIC_STORAGE'] || 'socrates'
9
+ end
10
+
11
+ VEC = /^\[.*\]$/
12
+ MAP = /^\{.*\}$/
13
+
14
+ describe "#create_database" do
15
+ it "returns 201 when creating a new database" do
16
+ resp = client.create_database("test-#{Time.now.to_i}")
17
+ resp.code.should == 201
18
+ end
19
+
20
+ it "returns 200 when database already exists" do
21
+ db = "test-#{Time.now.to_i}"
22
+ client.create_database(db)
23
+ resp = client.create_database(db)
24
+ resp.code.should == 200
25
+ end
26
+ end
27
+
28
+ describe "#database_info" do
29
+ before { client.create_database('test-database_info') }
30
+
31
+ it "returns 200 for existing database" do
32
+ resp = client.database_info('test-database_info')
33
+ resp.code.should == 200
34
+ resp.body.should include(':basis-t')
35
+ resp.body.should include(':db/alias')
36
+ end
37
+
38
+ it "returns database info for existing database" do
39
+ resp = client.database_info('test-database_info')
40
+ resp.body.should include(':basis-t')
41
+ resp.body.should include(':db/alias')
42
+ end
43
+
44
+ it "returns 404 for nonexistent database" do
45
+ pending "docs say 404 but seeing 500"
46
+ resp = client.database_info('zxvf')
47
+ resp.code.should == 404
48
+ end
49
+ end
50
+
51
+ describe "#transact" do
52
+ before { client.create_database('test-transact') }
53
+
54
+ it "returns correct response" do
55
+ pending "til valid transaction data given"
56
+ resp = client.transact('test-transact', "[:db/add 1 :some :value]")
57
+ resp.code.should == 200
58
+ resp.body.should match MAP
59
+ end
60
+ end
61
+
62
+ describe "#datoms" do
63
+ before { client.create_database('test-datoms') }
64
+
65
+ %w{eavt aevt avet vaet}.each do |index|
66
+ it "returns correct response for index '#{index}'" do
67
+ pending "possible bug" if index == 'vaet'
68
+ resp = client.datoms('test-datoms', index)
69
+ resp.code.should == 200
70
+ resp.body.should match VEC
71
+ end
72
+ end
73
+
74
+ it "raises 500 error for invalid index" do
75
+ expect { client.datoms('test-datoms', 'blarg') }.
76
+ to raise_error(RestClient::InternalServerError, /500 Internal Server Error/)
77
+ end
78
+
79
+ it "returns correct response with limit param" do
80
+ resp = client.datoms('test-datoms', "eavt", :limit => 0)
81
+ resp.code.should == 200
82
+ resp.body.should == "[]"
83
+ end
84
+ end
85
+
86
+ describe "#range" do
87
+ before { client.create_database('test-range') }
88
+
89
+ it "returns correct response with required attribute" do
90
+ resp = client.range('test-range', :a => "db/ident")
91
+ resp.code.should == 200
92
+ resp.body.should match VEC
93
+ end
94
+
95
+ it "raises 400 without required attribute" do
96
+ expect { client.range('test-range') }.
97
+ to raise_error(RestClient::BadRequest, /400 Bad Request/)
98
+ end
99
+ end
100
+
101
+ describe "#entity" do
102
+ before { client.create_database('test-entity') }
103
+
104
+ it "returns correct response" do
105
+ resp = client.entity('test-entity', 1)
106
+ resp.code.should == 200
107
+ resp.body.should match MAP
108
+ end
109
+
110
+ it "returns correct response with valid param" do
111
+ resp = client.entity('test-entity', 1, :since => 0)
112
+ resp.code.should == 200
113
+ resp.body.should match MAP
114
+ end
115
+ end
116
+
117
+ describe "#query" do
118
+ let(:client) { Datomic::Client.new datomic_uri }
119
+
120
+ it "returns a correct response" do
121
+ pending "til valid query given"
122
+ resp = client.query("[:find ?e :where [?e :id 1]]")
123
+ resp.code.should == 200
124
+ resp.body.should match VEC
125
+ end
126
+ end
127
+
128
+ describe "#monitor" do
129
+ before { client.create_database('test-monitor') }
130
+
131
+ it "returns a correct response" do
132
+ resp = client.monitor('test-monitor')
133
+ resp.code.should == 200
134
+ resp.body.should match(/\<script\>/)
135
+ end
136
+ end
137
+
138
+ describe "#events" do
139
+ before { client.create_database('test-events') }
140
+
141
+ it "returns correct response" do
142
+ begin
143
+ client.events('test-events') do |resp|
144
+ resp.code.should == "200"
145
+ # Don't see a cleaner way to quit after testing one event
146
+ raise Timeout::Error
147
+ end
148
+ rescue RestClient::RequestTimeout
149
+ end
150
+ end
151
+
152
+ it "returns a 503 for nonexistent db" do
153
+ expect { client.events('zzzz') }.
154
+ to raise_error(RestClient::ServiceUnavailable, /503 Service Unavailable/)
155
+ end
156
+ end
157
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: datomic-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gabriel Horner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.2.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: rest-client
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: This gem provides a simple way to use datomic's http API - http://docs.datomic.com/rest.html.
79
+ email: gabriel.horner@gmail.com
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - CHANGELOG.md
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - datomic-client.gemspec
89
+ - lib/datomic/client.rb
90
+ - spec/datomic_client_spec.rb
91
+ homepage: http://github.com/cldwalker/datomic-client
92
+ licenses: []
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 1.8.24
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: http client for datomic's API
115
+ test_files:
116
+ - spec/datomic_client_spec.rb