diametric 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +6 -14
  2. data/Gemfile +3 -3
  3. data/Jarfile +13 -6
  4. data/LICENSE.txt +2 -2
  5. data/README.md +57 -26
  6. data/Rakefile +1 -0
  7. data/bin/datomic-rest +1 -1
  8. data/bin/download-datomic +1 -1
  9. data/datomic_version.yml +2 -2
  10. data/diametric.gemspec +8 -7
  11. data/ext/diametric/DiametricCollection.java +45 -38
  12. data/ext/diametric/DiametricConnection.java +16 -15
  13. data/ext/diametric/DiametricDatabase.java +9 -8
  14. data/ext/diametric/DiametricEntity.java +104 -21
  15. data/ext/diametric/DiametricObject.java +12 -1
  16. data/ext/diametric/DiametricPeer.java +52 -31
  17. data/ext/diametric/DiametricService.java +2 -0
  18. data/ext/diametric/DiametricSet.java +11 -4
  19. data/ext/diametric/DiametricUUID.java +8 -1
  20. data/ext/diametric/DiametricUtils.java +90 -62
  21. data/lib/diametric.rb +1 -0
  22. data/lib/diametric/associations/collection.rb +103 -0
  23. data/lib/diametric/entity.rb +166 -103
  24. data/lib/diametric/persistence/common.rb +0 -44
  25. data/lib/diametric/persistence/peer.rb +53 -2
  26. data/lib/diametric/persistence/rest.rb +27 -1
  27. data/lib/diametric/query.rb +49 -31
  28. data/lib/diametric/rest_service.rb +8 -9
  29. data/lib/diametric/service_base.rb +7 -7
  30. data/lib/diametric/transactor.rb +6 -5
  31. data/lib/diametric/version.rb +1 -1
  32. data/lib/diametric_service.jar +0 -0
  33. data/spec/config/free-transactor-template.properties +6 -6
  34. data/spec/developer_query_spec.rb +17 -6
  35. data/spec/diametric/entity_spec.rb +62 -139
  36. data/spec/diametric/peer_api_spec.rb +23 -23
  37. data/spec/diametric/persistence/peer_spec.rb +73 -11
  38. data/spec/diametric/persistence/rest_spec.rb +108 -16
  39. data/spec/diametric/query_spec.rb +3 -3
  40. data/spec/diametric/rest_service_spec.rb +4 -4
  41. data/spec/diametric/schema_spec.rb +526 -0
  42. data/spec/diametric/transactor_spec.rb +5 -6
  43. data/spec/integration_spec.rb +7 -7
  44. data/spec/peer_integration_spec.rb +25 -1
  45. data/spec/peer_seattle_spec.rb +1 -2
  46. data/spec/spec_helper.rb +31 -4
  47. data/spec/support/cardinarity_many_example.rb +37 -0
  48. data/spec/support/entities.rb +127 -0
  49. data/spec/support/has_a_example.rb +31 -0
  50. data/spec/support/has_many_example.rb +79 -0
  51. data/spec/support/persistence_examples.rb +13 -5
  52. data/spec/support/various_types_examples.rb +163 -0
  53. data/spec/test_version_file.yml +2 -2
  54. metadata +66 -15
@@ -23,22 +23,22 @@ describe "Transactor Service", :transactor =>true do
23
23
  end
24
24
 
25
25
  it "should return false for version no" do
26
- transactor.datomic_conf_file?("datomic-free-0.8.4122").should be_false
26
+ transactor.datomic_conf_file?("0.9.4497").should be_false
27
27
  end
28
28
 
29
29
  it "should know datomic version specified" do
30
- transactor.datomic_version("spec/test_version_file.yml").should == "datomic-free-0.8.4122"
31
- transactor.datomic_version("datomic-free-0.8.4122").should == "datomic-free-0.8.4122"
30
+ transactor.datomic_version("spec/test_version_file.yml").should == ["free", "0.9.4497"]
31
+ transactor.datomic_version("0.9.4497").should == ["free", "0.9.4497"]
32
32
  end
33
33
 
34
34
  it "should know the specified version of datomic has been downloaded" do
35
35
  transactor.downloaded?("spec/test_version_file.yml", "tmp/datomic").should be_false
36
- transactor.downloaded?("datomic-free-0.8.4122", "tmp/datomic").should be_false
36
+ transactor.downloaded?("0.9.4497", "tmp/datomic").should be_false
37
37
 
38
38
  transactor.download("spec/test_version_file.yml", "tmp/datomic")
39
39
 
40
40
  transactor.downloaded?("spec/test_version_file.yml", "tmp/datomic").should be_true
41
- transactor.downloaded?("datomic-free-0.8.4122", "tmp/datomic").should be_true
41
+ transactor.downloaded?("0.9.4497", "tmp/datomic").should be_true
42
42
  end
43
43
 
44
44
  context Diametric::Transactor do
@@ -64,5 +64,4 @@ describe "Transactor Service", :transactor =>true do
64
64
  transactor.stop
65
65
  end
66
66
  end
67
-
68
67
  end
@@ -7,10 +7,10 @@ require 'securerandom'
7
7
  # bin/rest 9000 test datomic:mem://
8
8
 
9
9
  describe Diametric::Entity, :integration => true do
10
- before(:all) do
10
+ before do
11
11
  @datomic_uri = ENV['DATOMIC_URI'] || 'http://localhost:46291'
12
12
  @storage = ENV['DATOMIC_STORAGE'] || 'free'
13
- @dbname = ENV['DATOMIC_NAME'] || "test-#{SecureRandom.uuid}"
13
+ @dbname = ENV['DATOMIC_NAME'] || "integratin-test-#{SecureRandom.uuid}"
14
14
  @client = Datomic::Client.new @datomic_uri, @storage
15
15
  @client.create_database(@dbname)
16
16
  sleep 0.5
@@ -24,8 +24,7 @@ describe Diametric::Entity, :integration => true do
24
24
  end
25
25
 
26
26
  describe "with a schema" do
27
- before(:all) do
28
- @client.transact(@dbname, Person.schema)
27
+ before do
29
28
  @client.transact(@dbname, Goat.schema)
30
29
  end
31
30
 
@@ -40,13 +39,14 @@ describe Diametric::Entity, :integration => true do
40
39
  end
41
40
 
42
41
  describe "with an entity" do
43
- before(:all) do
42
+ before do
43
+ @client.transact(@dbname, Goat.schema)
44
44
  goat = Goat.new(:name => "Josef", :birthday => DateTime.parse("1976-09-04"))
45
45
  @client.transact(@dbname, goat.tx_data)
46
46
  end
47
47
 
48
48
  it "can query for that entity" do
49
- query, args = Diametric::Query.new(Goat).where(:name => "Josef").data
49
+ query, args = Diametric::Query.new(Goat, nil, true).where(:name => "Josef").data
50
50
  args = args.unshift({:"db/alias" => "#{@storage}/#{@dbname}"})
51
51
  resp = @client.query(query, args)
52
52
  resp.code.should == 200
@@ -67,7 +67,7 @@ describe Diametric::Entity, :integration => true do
67
67
  end
68
68
 
69
69
  describe "with persistence module" do
70
- before(:all) do
70
+ before do
71
71
  Robin.create_schema
72
72
  end
73
73
 
@@ -64,7 +64,7 @@ describe Diametric::Entity, :integration => true, :jruby => true do
64
64
  Penguin.new(name: "Mary Jen.", birthday: DateTime.parse('1999-12-31'), awesomeness: true).save
65
65
  Penguin.new(name: "Mary Jr.", birthday: DateTime.parse('2013-01-01'), awesomeness: false).save
66
66
  Penguin.new(name: "Mary Jay.", birthday: DateTime.parse('1850-02-22'), awesomeness: false).save
67
- query = Penguin.filter(:<, :birthday, DateTime.parse('1900-01-01'))
67
+ query = Penguin.filter(@conn, :<, :birthday, DateTime.parse('1900-01-01'))
68
68
  result = query.all
69
69
  result.size.should == 2
70
70
  result.collect(&:name).should =~ ["Mary Jay.", "Mary Jo."]
@@ -150,6 +150,30 @@ describe Diametric::Entity, :integration => true, :jruby => true do
150
150
  account2.deposit.should include(100.0)
151
151
  account2.deposit.should include(200.0)
152
152
  end
153
+ end
154
+
155
+ context 'issue43' do
156
+ before do
157
+ @datomic_uri = 'datomic:mem://issue43'
158
+ @conn_issue43 = Diametric::Persistence.establish_base_connection({:uri => @datomic_uri})
159
+ This::Bug.create_schema(@conn_issue43).get
160
+ Outermost::Outer::Inner::Innermost.create_schema(@conn_issue43).get
161
+ end
162
+
163
+ after do
164
+ @conn_issue43.release
165
+ end
166
+
167
+ it 'should get all entities' do
168
+ This::Bug.new(id: '123').save
169
+ result = This::Bug.all
170
+ result.first.id.should == '123'
171
+ end
153
172
 
173
+ it 'should get all entities of nested modules' do
174
+ Outermost::Outer::Inner::Innermost.new(name: 'nested').save
175
+ result = Outermost::Outer::Inner::Innermost.all
176
+ result.first.name.should == 'nested'
177
+ end
154
178
  end
155
179
  end
@@ -94,8 +94,7 @@ describe Diametric::Entity, :integration => true, :jruby => true do
94
94
 
95
95
  result = []
96
96
  neighborhood.parse_tx_data(neighborhood.tx_data, result)
97
- result.first[":neighborhood/district"].to_s.should match(/^\d+/)
98
-
97
+ result.first[:"neighborhood/district"].to_s.should match(/^\d+/)
99
98
  neighborhood.save(@n_conn2)
100
99
  district.tx_data.should be_empty
101
100
  neighborhood.tx_data.should be_empty
@@ -28,9 +28,11 @@ RSpec.configure do |c|
28
28
  c.treat_symbols_as_metadata_keys_with_true_values = true
29
29
 
30
30
  c.before(:suite) do
31
- @rest = Diametric::RestService.new("spec/test_version_file.yml", "tmp/datomic")
32
- @rest.start(:port => 46291, :db_alias => @storage, :uri => "datomic:mem://")
33
- PID = @rest.pid
31
+ unless ENV['RESTSERVICE']
32
+ @rest = Diametric::RestService.new("spec/test_version_file.yml", "tmp/datomic")
33
+ @rest.start(:port => 46291, :db_alias => @storage, :uri => "datomic:mem://")
34
+ PID = @rest.pid
35
+ end
34
36
  if ENV['TRANSACTOR']
35
37
  FileUtils.cp(File.join('spec', 'config', 'logback.xml'), File.join('bin', 'logback.xml'))
36
38
  end
@@ -38,13 +40,38 @@ RSpec.configure do |c|
38
40
 
39
41
  c.after(:suite) do
40
42
  Diametric::Persistence::Peer.shutdown(true) if is_jruby?
41
- Process.kill("HUP", PID)
43
+ unless ENV['RESTSERVICE']
44
+ Process.kill("HUP", PID)
45
+ end
42
46
  if ENV['TRANSACTOR']
43
47
  FileUtils.rm(File.join('bin', 'logback.xml'), :force => true)
44
48
  end
45
49
  end
46
50
  end
47
51
 
52
+ RSpec::Matchers.define :be_an_equivalent_hash do |expected|
53
+ match do |actual|
54
+ status = true
55
+ expected.keys.each do |k|
56
+ next if k == :"db/id"
57
+ status = false if actual[k].nil?
58
+ status = false unless actual[k] == expected[k]
59
+ end
60
+ status
61
+ end
62
+ end
63
+
64
+ RSpec::Matchers.define :be_an_equivalent_array do |expected|
65
+ match do |actual|
66
+ status = true
67
+ expected.each_with_index do |e, index|
68
+ next if e.kind_of?(String) && (e.gsub(/ /, "") == "#db/id[:db.part/user]")
69
+ status = false unless actual[index] == e
70
+ end
71
+ status
72
+ end
73
+ end
74
+
48
75
  shared_examples "ActiveModel" do |model|
49
76
  require 'test/unit/assertions'
50
77
  require 'active_model/lint'
@@ -0,0 +1,37 @@
1
+ shared_examples "supports cardinality many" do
2
+ describe "entity instance" do
3
+ let(:model) { model_class.new }
4
+
5
+ it "can save" do
6
+ model.words = ["hopefully", "likely", "possibly"]
7
+ model.save.should be_true
8
+ model.should be_persisted
9
+
10
+ model.class.all.first.words.should == Set.new(["hopefully", "likely", "possibly"])
11
+ end
12
+
13
+ describe "#assign_attributes" do
14
+ let(:words) {
15
+ model.words = ["sadlly", "happily", "joyfully"]
16
+ model.save
17
+ model
18
+ }
19
+
20
+ it "updates words" do
21
+ new_values = { "words" => ["calmly", "peacefully", "joyfully"] }
22
+ words.update_attributes(new_values)
23
+
24
+ words.should_not be_changed
25
+ words.words.should == Set.new(["calmly", "peacefully", "joyfully"])
26
+
27
+ if model_class.ancestors.include? Diametric::Persistence::Peer
28
+ result = model_class.where({:words => new_values["words"]}, nil, true).first
29
+ else
30
+ # not sure, but for some reason, REST likes singular.
31
+ result = model_class.where({:word => new_values["words"]}).first
32
+ end
33
+ result.dbid.should == words.dbid
34
+ end
35
+ end
36
+ end
37
+ end
@@ -72,6 +72,77 @@ class Mouse
72
72
  attribute :age, Integer
73
73
  end
74
74
 
75
+ class ScarletMacaw
76
+ include Diametric::Entity
77
+ include Diametric::Persistence::Peer
78
+
79
+ attribute :name, String
80
+ attribute :description, String, :fulltext => true
81
+ attribute :talkative, Boolean
82
+ attribute :colors, Integer
83
+ attribute :average_speed, Float
84
+ attribute :observed, DateTime
85
+ attribute :case_no, UUID, :index => true
86
+ attribute :serial, UUID, :unique => :value
87
+ end
88
+
89
+ class Peacock
90
+ include Diametric::Entity
91
+ include Diametric::Persistence::REST
92
+
93
+ attribute :name, String
94
+ attribute :description, String, :fulltext => true
95
+ attribute :talkative, Boolean
96
+ attribute :colors, Integer
97
+ attribute :average_speed, Float
98
+ attribute :observed, DateTime
99
+ # REST failes to save UUID
100
+ #attribute :case_no, UUID, :index => true
101
+ #attribute :serial, UUID, :unique => :value
102
+ end
103
+
104
+ class MyWords
105
+ include Diametric::Entity
106
+ include Diametric::Persistence::Peer
107
+
108
+ attribute :words, String, :cardinality => :many
109
+ end
110
+
111
+ class YourWords
112
+ include Diametric::Entity
113
+ include Diametric::Persistence::REST
114
+
115
+ attribute :words, String, :cardinality => :many
116
+ end
117
+
118
+ class Cage
119
+ include Diametric::Entity
120
+ include Diametric::Persistence::Peer
121
+
122
+ attribute :pet, Ref
123
+ end
124
+
125
+ class Box
126
+ include Diametric::Entity
127
+ include Diametric::Persistence::REST
128
+
129
+ attribute :pet, Ref
130
+ end
131
+
132
+ class BigCage
133
+ include Diametric::Entity
134
+ include Diametric::Persistence::Peer
135
+
136
+ attribute :pets, Ref, :cardinality => :many
137
+ end
138
+
139
+ class BigBox
140
+ include Diametric::Entity
141
+ include Diametric::Persistence::REST
142
+
143
+ attribute :pets, Ref, :cardinality => :many
144
+ end
145
+
75
146
  class Author
76
147
  include Diametric::Entity
77
148
  include Diametric::Persistence::Peer
@@ -88,6 +159,38 @@ class Book
88
159
  attribute :authors, Ref, :cardinality => :many
89
160
  end
90
161
 
162
+ class Writer
163
+ include Diametric::Entity
164
+ include Diametric::Persistence::REST
165
+
166
+ attribute :name, String
167
+ attribute :books, Ref, :cardinality => :many
168
+ end
169
+
170
+ class Article
171
+ include Diametric::Entity
172
+ include Diametric::Persistence::REST
173
+
174
+ attribute :title, String
175
+ attribute :authors, Ref, :cardinality => :many
176
+ end
177
+
178
+ class Role
179
+ include Diametric::Entity
180
+ include Diametric::Persistence::Peer
181
+
182
+ attribute :type, Ref
183
+ enum :type, [:accountant, :manager, :developer]
184
+ end
185
+
186
+ class Position
187
+ include Diametric::Entity
188
+ include Diametric::Persistence::REST
189
+
190
+ attribute :type, Ref
191
+ enum :type, [:accountant, :manager, :developer]
192
+ end
193
+
91
194
  class Choice
92
195
  include Diametric::Entity
93
196
  include Diametric::Persistence::Peer
@@ -157,3 +260,27 @@ class District
157
260
  attribute :region, Ref, :cardinality => :one, :doc => "A district region enum value"
158
261
  enum :region, [:n, :ne, :e, :se, :s, :sw, :w, :nw]
159
262
  end
263
+
264
+ # issue 43
265
+ module This
266
+ class Bug
267
+ include Diametric::Entity
268
+ include Diametric::Persistence::Peer
269
+
270
+ attribute :id, String, index: true
271
+ attribute :name, String
272
+ end
273
+ end
274
+
275
+ module Outermost
276
+ module Outer
277
+ module Inner
278
+ class Innermost
279
+ include Diametric::Entity
280
+ include Diametric::Persistence::Peer
281
+
282
+ attribute :name, String
283
+ end
284
+ end
285
+ end
286
+ end
@@ -0,0 +1,31 @@
1
+ shared_examples "supports has_one association" do
2
+ describe "entity instance" do
3
+ let(:parent) { parent_class.new }
4
+ let(:child) { child_class.new }
5
+
6
+ it "can save child" do
7
+ # similar to thing.pet_id = pet.id; pet.save
8
+ # diametric does pet.save; thing.pet = pet.dbid
9
+ child.name = "Sophia"
10
+ child.age = 5
11
+ parent.pet = child
12
+
13
+ child.should be_persisted
14
+ child.dbid.to_i.should > 0
15
+ child.class.all.first.name.should == "Sophia"
16
+ end
17
+
18
+ it "can save parent" do
19
+ child.name = "Jacob"
20
+ child.age = 3
21
+ parent.pet = child
22
+ parent.save
23
+
24
+ parent.should be_persisted
25
+ parent.dbid.to_i.should > 0
26
+ searched_child = parent.class.all.first.pet
27
+ searched_child.name.should == "Jacob"
28
+ searched_child.age.should == 3
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,79 @@
1
+ shared_examples "supporting has_many association" do
2
+ describe "entity instance" do
3
+ let(:parent) { parent_class.new }
4
+ let(:child) { child_class.new }
5
+
6
+ it "can save child" do
7
+ child.name = "Emma"
8
+ child.age = 15
9
+ parent.pets << child
10
+
11
+ child.should be_persisted
12
+ child.dbid.to_i.should > 0
13
+ end
14
+
15
+ it "can save parent" do
16
+ child.name = "Ethan"
17
+ child.age = 14
18
+ parent.pets << child
19
+ parent.save
20
+
21
+ parent.should be_persisted
22
+ parent.dbid.to_i.should > 0
23
+ searched_children = parent.class.first.pets
24
+ searched_children.collect(&:name).should include "Ethan"
25
+ searched_children.collect(&:age).should include 14
26
+ end
27
+
28
+ it "can find children" do
29
+ child1 = child_class.new(name: "Michael", age: 10)
30
+ parent.pets << child1
31
+ child2 = child_class.new(name: "Mia", age: 9)
32
+ parent.pets << child2
33
+ parent.save
34
+
35
+ searched_parent = parent.class.first
36
+ searched_parent.pets.size.should == 2
37
+ searched_parent.pets.collect(&:name).should =~ ["Michael", "Mia"]
38
+ searched_parent.pets.collect(&:age).should =~ [10, 9]
39
+ searched_parent.pets.empty?.should == false
40
+ end
41
+
42
+ it "can destory child" do
43
+ child1 = child_class.new(name: "Alexander", age: 5)
44
+ child2 = child_class.new(name: "Abigail", age: 6)
45
+ parent.pets = [child1, child2]
46
+ parent.save
47
+
48
+ searched_parent = parent.class.first
49
+ searched_parent.pets.size.should == 2
50
+
51
+ searched_parent.pets.destroy(child1)
52
+ searched_parent.pets.size.should == 1
53
+ searched_parent.pets.collect(&:name).should == ["Abigail"]
54
+ searched_parent.pets.collect(&:age).should == [6]
55
+
56
+ searched_children = child_class.all
57
+ searched_children.size.should == 1
58
+ searched_children.first.dbid.should == child2.dbid
59
+ end
60
+
61
+ it "can delete child" do
62
+ child1 = child_class.new(name: "Joseph", age: 1)
63
+ child2 = child_class.new(name: "Janet", age: 2)
64
+ parent.pets = [child1, child2]
65
+ parent.save
66
+
67
+ searched_parent = parent.class.first
68
+ searched_parent.pets.size.should == 2
69
+
70
+ searched_parent.pets.delete(child1, child2)
71
+ searched_parent.pets.size.should == 0
72
+
73
+ searched_children = child_class.all
74
+ searched_children.size.should == 2
75
+ searched_children.collect(&:name).should =~ ["Joseph", "Janet"]
76
+ searched_children.collect(&:age).should =~ [1, 2]
77
+ end
78
+ end
79
+ end