entity_store_sequel 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/entity_store_sequel/postgres_entity_store.rb +226 -0
- data/lib/entity_store_sequel/version.rb +3 -0
- data/lib/entity_store_sequel.rb +3 -0
- data/lib/sequel/core_ext.rb +5 -0
- data/lib/tasks/entity_store.rake +11 -0
- data/spec/entity_store_sequel/postgres_entity_store_spec.rb +242 -0
- data/spec/entity_store_spec.rb +59 -0
- data/spec/spec_helper.rb +42 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ca75da75c0371ee57e8f87d2177691af50e1c231
|
4
|
+
data.tar.gz: a64bb369cb3b59e6fc065fdc209d4011499a8137
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e31b881de426b9590058dfe63cbc877e1921da6560e93b00c43e8a4082ffe2b75567861bfb47b4f5628c987caa9a8379afa4f524e7eb106ce0c266c48b0aecb
|
7
|
+
data.tar.gz: 0a7a1d86c96dc4cabd20b4b85d2cff026c74ffd197a96705058081f15c37a161504aa15190b6fa386da3941de709dcb5f93f94e54141d7044d9d857147c5f550
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'pigeon_hole'
|
5
|
+
require 'entity_store'
|
6
|
+
|
7
|
+
module EntityStoreSequel
|
8
|
+
class PostgresEntityStore
|
9
|
+
include EntityStore::Logging
|
10
|
+
|
11
|
+
Sequel.extension :pg_array_ops
|
12
|
+
Sequel.extension :pg_json_ops
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :connection_string
|
16
|
+
attr_writer :connect_timeout
|
17
|
+
|
18
|
+
def database
|
19
|
+
return @_database if @_database
|
20
|
+
|
21
|
+
@_database ||= Sequel.connect(connection_string)
|
22
|
+
@_database.extension :pg_array
|
23
|
+
@_database.extension :pg_json
|
24
|
+
|
25
|
+
@_database
|
26
|
+
end
|
27
|
+
|
28
|
+
def init
|
29
|
+
unless database.table_exists?(:entities)
|
30
|
+
database.create_table :entities do
|
31
|
+
column :id, :char, primary_key: true, size: 24
|
32
|
+
String :_type
|
33
|
+
integer :snapshot_key
|
34
|
+
integer :version
|
35
|
+
column :snapshot, :jsonb
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
unless database.table_exists?(:entity_events)
|
40
|
+
database.create_table :entity_events do
|
41
|
+
column :id, :char, primary_key: true, size: 24
|
42
|
+
String :_type
|
43
|
+
column :_entity_id, :char, size: 24
|
44
|
+
integer :entity_version
|
45
|
+
column :data, :jsonb
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def open
|
52
|
+
PostgresEntityStore.database
|
53
|
+
end
|
54
|
+
|
55
|
+
def entities
|
56
|
+
@entities_collection ||= open[:entities]
|
57
|
+
end
|
58
|
+
|
59
|
+
def events
|
60
|
+
@events_collection ||= open[:entity_events]
|
61
|
+
end
|
62
|
+
|
63
|
+
def clear
|
64
|
+
open.drop_table(:entities, :entity_events)
|
65
|
+
@entities_collection = nil
|
66
|
+
@events_collection = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def ensure_indexes
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_entity(entity, id = BSON::ObjectId.new)
|
73
|
+
entities.insert(:id => id.to_s, :_type => entity.class.name, :version => entity.version)
|
74
|
+
id.to_s
|
75
|
+
end
|
76
|
+
|
77
|
+
def save_entity(entity)
|
78
|
+
entities.where(:id => entity.id).update(:version => entity.version)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Public: create a snapshot of the entity and store in the entities collection
|
82
|
+
#
|
83
|
+
def snapshot_entity(entity)
|
84
|
+
if entity.class.respond_to? :entity_store_snapshot_key
|
85
|
+
# If there is a snapshot key, store it too
|
86
|
+
snapshot_key = entity.class.entity_store_snapshot_key
|
87
|
+
else
|
88
|
+
# Otherwise, make sure there isn't one set
|
89
|
+
snapshot_key = nil
|
90
|
+
end
|
91
|
+
|
92
|
+
unless entities[:id => entity.id]
|
93
|
+
entities.insert(:id => entity.id, :_type => entity.class.name, :version => entity.version)
|
94
|
+
end
|
95
|
+
|
96
|
+
entities
|
97
|
+
.where(:id => entity.id)
|
98
|
+
.update(:snapshot => PigeonHole.generate(entity.attributes), :snapshot_key => snapshot_key )
|
99
|
+
end
|
100
|
+
|
101
|
+
# Public - remove the snapshot for an entity
|
102
|
+
#
|
103
|
+
def remove_entity_snapshot(id)
|
104
|
+
entities.where(:id => id).update(:snapshot => nil)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Public: remove all snapshots
|
108
|
+
#
|
109
|
+
# type - String optional class name for the entity
|
110
|
+
#
|
111
|
+
def remove_snapshots(type=nil)
|
112
|
+
if type
|
113
|
+
entities.where(:_type => type).update(:snapshot => nil)
|
114
|
+
else
|
115
|
+
entities.update(:snapshot => nil)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def add_events(items)
|
120
|
+
events_with_id = items.map { |e| [ BSON::ObjectId.new, e ] }
|
121
|
+
add_events_with_ids(events_with_id)
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_events_with_ids(event_id_map)
|
125
|
+
event_id_map.each do |id, event|
|
126
|
+
doc = {
|
127
|
+
:id => id.to_s,
|
128
|
+
:_type => event.class.name,
|
129
|
+
:_entity_id => BSON::ObjectId.from_string(event.entity_id).to_s,
|
130
|
+
:entity_version => event.entity_version,
|
131
|
+
:data => PigeonHole.generate(event.attributes),
|
132
|
+
}
|
133
|
+
events.insert(doc)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Public: loads the entity from the store, including any available snapshots
|
138
|
+
# then loads the events to complete the state
|
139
|
+
#
|
140
|
+
# ids - Array of Strings representation of BSON::ObjectId
|
141
|
+
# options - Hash of options (default: {})
|
142
|
+
# :raise_exception - Boolean (default: true)
|
143
|
+
#
|
144
|
+
# Returns an array of entities
|
145
|
+
def get_entities(ids, options={})
|
146
|
+
ids.each do |id|
|
147
|
+
begin
|
148
|
+
BSON::ObjectId.from_string(id)
|
149
|
+
rescue BSON::InvalidObjectId
|
150
|
+
raise NotFound.new(id) if options.fetch(:raise_exception, true)
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
entities.where(:id => ids).map do |attrs|
|
156
|
+
begin
|
157
|
+
entity_type = EntityStore::Config.load_type(attrs[:_type])
|
158
|
+
|
159
|
+
# Check if there is a snapshot key in use
|
160
|
+
if entity_type.respond_to? :entity_store_snapshot_key
|
161
|
+
active_key = entity_type.entity_store_snapshot_key
|
162
|
+
|
163
|
+
# Discard the snapshot if the keys don't match
|
164
|
+
unless active_key == attrs[:snapshot_key]
|
165
|
+
attrs.delete(:snapshot)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
if attrs[:snapshot]
|
170
|
+
hash = attrs[:snapshot].to_h
|
171
|
+
entity = entity_type.new(hash)
|
172
|
+
else
|
173
|
+
entity = entity_type.new({'id' => attrs[:id].to_s })
|
174
|
+
end
|
175
|
+
rescue => e
|
176
|
+
log_error "Error loading type #{attrs[:_type]}", e
|
177
|
+
raise
|
178
|
+
end
|
179
|
+
|
180
|
+
entity
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
# Public: get events for an array of criteria objects
|
186
|
+
# because each entity could have a different reference
|
187
|
+
# version this allows optional criteria to be specifed
|
188
|
+
#
|
189
|
+
#
|
190
|
+
# criteria - Hash :id mandatory, :since_version optional
|
191
|
+
#
|
192
|
+
# Examples
|
193
|
+
#
|
194
|
+
# get_events_for_criteria([ { id: "23232323"}, { id: "2398429834", since_version: 4 } ] )
|
195
|
+
#
|
196
|
+
# Returns Hash with id as key and Array of Event instances as value
|
197
|
+
def get_events(criteria)
|
198
|
+
return {} if criteria.empty?
|
199
|
+
|
200
|
+
result = {}
|
201
|
+
|
202
|
+
criteria.each do |item|
|
203
|
+
raise ArgumentError.new(":id missing from criteria") unless item[:id]
|
204
|
+
|
205
|
+
query = events.where(:_entity_id => item[:id])
|
206
|
+
|
207
|
+
if item[:since_version]
|
208
|
+
query = query.where('entity_version > ?', item[:since_version])
|
209
|
+
end
|
210
|
+
|
211
|
+
result[item[:id]] = query.order(:entity_version, :id).map do |attrs|
|
212
|
+
begin
|
213
|
+
hash = attrs[:data].to_h
|
214
|
+
hash[:entity_version] = attrs[:entity_version]
|
215
|
+
EntityStore::Config.load_type(attrs[:_type]).new(hash)
|
216
|
+
rescue => e
|
217
|
+
log_error "Error loading type #{attrs[:_type]}", e
|
218
|
+
next
|
219
|
+
end
|
220
|
+
end.compact
|
221
|
+
end
|
222
|
+
|
223
|
+
result
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PostgresEntityStore do
|
4
|
+
class DummyEntity
|
5
|
+
include EntityStore::Entity
|
6
|
+
|
7
|
+
attr_accessor :name, :description
|
8
|
+
|
9
|
+
def set_name(new_name)
|
10
|
+
record_event DummyEntityNameSet.new(name: new_name)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class DummyEntityWithDate
|
15
|
+
include EntityStore::Entity
|
16
|
+
|
17
|
+
attr_accessor :name, :description, :date, :symbol, :symbol_hash
|
18
|
+
attr_accessor :nested_hash
|
19
|
+
|
20
|
+
def set_name(new_name)
|
21
|
+
record_event DummyEntityNameSet.new(name: new_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class DummyEntityWithSnapshotKey < DummyEntity
|
26
|
+
def self.entity_store_snapshot_key
|
27
|
+
@entity_store_snapshot_key ||= 1
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.increment_entity_store_snapshot_key!
|
31
|
+
@entity_store_snapshot_key = entity_store_snapshot_key + 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class DummyEntityNameSet
|
36
|
+
include EntityStore::Event
|
37
|
+
|
38
|
+
attr_accessor :name
|
39
|
+
|
40
|
+
def apply(entity)
|
41
|
+
entity.name = self.name
|
42
|
+
end
|
43
|
+
|
44
|
+
def ==(other)
|
45
|
+
# Crude check relying on inspect, ok for tests
|
46
|
+
self.inspect == other.inspect
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:store) do
|
51
|
+
described_class.connection_string = ENV['SQL_CONNECTION'] || 'postgres://localhost/cronofy_test'
|
52
|
+
described_class.init
|
53
|
+
described_class.new
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "event storage" do
|
57
|
+
let(:entity_id) { random_object_id }
|
58
|
+
|
59
|
+
let(:first_event) { DummyEntityNameSet.new(:entity_id => entity_id, :entity_version => 1, :name => random_string) }
|
60
|
+
let(:second_event) { DummyEntityNameSet.new(:entity_id => entity_id, :entity_version => 2, :name => random_string) }
|
61
|
+
let(:third_event) { DummyEntityNameSet.new(:entity_id => entity_id, :entity_version => 2, :name => random_string) }
|
62
|
+
let(:unrelated_event) { DummyEntityNameSet.new(:entity_id => random_object_id, :entity_version => 4, :name => random_string) }
|
63
|
+
let(:fourth_event) { DummyEntityNameSet.new(:entity_id => entity_id, :entity_version => 3, :name => random_string) }
|
64
|
+
|
65
|
+
before do
|
66
|
+
store.add_events([ second_event, unrelated_event, first_event, third_event, fourth_event ])
|
67
|
+
end
|
68
|
+
|
69
|
+
subject { store.get_events( [{ id: event_entity_id, since_version: since_version }])[event_entity_id] }
|
70
|
+
|
71
|
+
context "all events" do
|
72
|
+
let(:event_entity_id) { entity_id }
|
73
|
+
let(:since_version) { 0 }
|
74
|
+
|
75
|
+
it "should return the four events in order" do
|
76
|
+
subject.should == [first_event, second_event, third_event, fourth_event]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "subset of events" do
|
81
|
+
let(:event_entity_id) { entity_id }
|
82
|
+
let(:since_version) { second_event.entity_version }
|
83
|
+
|
84
|
+
it "should only include events greater than the given version" do
|
85
|
+
subject.should == [ fourth_event ]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "no events" do
|
90
|
+
let(:event_entity_id) { random_object_id }
|
91
|
+
let(:since_version) { 0 }
|
92
|
+
|
93
|
+
it "should return an empty array" do
|
94
|
+
subject.should be_empty
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#get_entities" do
|
100
|
+
let(:entity_class) { DummyEntityWithDate }
|
101
|
+
let(:entity_date) { random_time }
|
102
|
+
|
103
|
+
let(:saved_entity) do
|
104
|
+
entity = entity_class.new(
|
105
|
+
:name => random_string,
|
106
|
+
:description => random_string,
|
107
|
+
:date => entity_date,
|
108
|
+
:symbol => :foo,
|
109
|
+
:symbol_hash => { foo: :bar },
|
110
|
+
:nested_hash => { foo: { bar: :baz } },
|
111
|
+
)
|
112
|
+
entity.id = store.add_entity(entity)
|
113
|
+
entity
|
114
|
+
end
|
115
|
+
|
116
|
+
let(:id) { saved_entity.id }
|
117
|
+
let(:options) { { } }
|
118
|
+
|
119
|
+
subject { store.get_entities( [ id ], options) }
|
120
|
+
|
121
|
+
it "should retrieve an entity from the store with the same ID" do
|
122
|
+
subject.first.id.should == saved_entity.id
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should retrieve an entity from the store with the same class" do
|
126
|
+
subject.first.class.should == saved_entity.class
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should have the same version" do
|
130
|
+
subject.first.version.should == saved_entity.version
|
131
|
+
end
|
132
|
+
|
133
|
+
context "when a snapshot does not exist" do
|
134
|
+
it "should not have set the name" do
|
135
|
+
subject.first.name.should be_nil
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should not have a date set" do
|
139
|
+
subject.first.date.should be_nil
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should not have a symbol set" do
|
143
|
+
subject.first.symbol.should be_nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "when a snapshot exists" do
|
148
|
+
before do
|
149
|
+
saved_entity.version = 10
|
150
|
+
store.snapshot_entity(saved_entity)
|
151
|
+
end
|
152
|
+
|
153
|
+
context "when a snapshot key not in use" do
|
154
|
+
it "should have set the name" do
|
155
|
+
subject.first.name.should == saved_entity.name
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should have a date set" do
|
159
|
+
subject.first.date.should == saved_entity.date
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should have a symbol set" do
|
163
|
+
subject.first.symbol.should == :foo
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should have a symbol hash set" do
|
167
|
+
subject.first.symbol_hash.should == { "foo" => :bar }
|
168
|
+
subject.first.nested_hash.should == { "foo" => { "bar" => :baz } }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when a snapshot key is in use" do
|
173
|
+
let(:entity_class) { DummyEntityWithSnapshotKey }
|
174
|
+
|
175
|
+
context "when the key matches the class's key" do
|
176
|
+
it "should have set the name" do
|
177
|
+
subject.first.name.should == saved_entity.name
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "when the key does not match the class's key" do
|
182
|
+
before do
|
183
|
+
entity_class.increment_entity_store_snapshot_key!
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should ignore the invalidated snapshot" do
|
187
|
+
subject.first.name.should be_nil
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "context when enable exceptions" do
|
194
|
+
let(:options) do
|
195
|
+
{ raise_exception: true }
|
196
|
+
end
|
197
|
+
|
198
|
+
context "when invalid id format passed" do
|
199
|
+
let(:id) { random_string }
|
200
|
+
|
201
|
+
it "should raise not found" do
|
202
|
+
expect { subject }.to raise_error(NotFound)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "#snapshot_entity" do
|
210
|
+
let(:entity_class) { DummyEntityWithDate }
|
211
|
+
|
212
|
+
let(:entity) do
|
213
|
+
entity_class.new(:id => random_object_id, :version => random_integer, :name => random_string)
|
214
|
+
end
|
215
|
+
|
216
|
+
let(:saved_entity) do
|
217
|
+
store.entities.where(:id => entity.id).first
|
218
|
+
end
|
219
|
+
|
220
|
+
let(:snapshot) { saved_entity[:snapshot] }
|
221
|
+
|
222
|
+
subject { store.snapshot_entity(entity) }
|
223
|
+
|
224
|
+
it "should add a snaphot to the entity record" do
|
225
|
+
subject
|
226
|
+
|
227
|
+
snapshot['id'].should eq(entity.id)
|
228
|
+
snapshot['version'].should eq(entity.version)
|
229
|
+
snapshot['name'].should eq(entity.name)
|
230
|
+
snapshot['description'].should eq(entity.description)
|
231
|
+
end
|
232
|
+
|
233
|
+
context "entity with snapshot key" do
|
234
|
+
let(:entity_class) { DummyEntityWithSnapshotKey }
|
235
|
+
|
236
|
+
it "should store the snapshot key" do
|
237
|
+
subject
|
238
|
+
saved_entity[:snapshot_key].should == entity.class.entity_store_snapshot_key
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class DummyEntity
|
4
|
+
include Entity
|
5
|
+
|
6
|
+
attr_accessor :name
|
7
|
+
|
8
|
+
def set_name(name)
|
9
|
+
record_event DummyEntityNameSet.new(name: name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class DummyEntityNameSet
|
14
|
+
include Event
|
15
|
+
|
16
|
+
attr_accessor :name
|
17
|
+
|
18
|
+
def apply(entity)
|
19
|
+
entity.name = name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class DummyEntitySubscriber
|
24
|
+
class << self
|
25
|
+
attr_accessor :event_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def dummy_entity_name_set(event)
|
29
|
+
DummyEntitySubscriber.event_name = event.name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "end to end" do
|
34
|
+
before(:each) do
|
35
|
+
PostgresEntityStore.connection_string = ENV['SQL_CONNECTION'] || 'postgres://localhost/cronofy_test'
|
36
|
+
PostgresEntityStore.init
|
37
|
+
|
38
|
+
EntityStore::Config.setup do |config|
|
39
|
+
config.store = PostgresEntityStore.new
|
40
|
+
config.event_subscribers << DummyEntitySubscriber
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when save entity" do
|
45
|
+
let(:name) { random_string }
|
46
|
+
before(:each) do
|
47
|
+
@entity = DummyEntity.new
|
48
|
+
@entity.set_name name
|
49
|
+
@id = Store.new.save @entity
|
50
|
+
end
|
51
|
+
|
52
|
+
it "publishes event to the subscriber" do
|
53
|
+
DummyEntitySubscriber.event_name.should eq(name)
|
54
|
+
end
|
55
|
+
it "is retrievable with the events applied" do
|
56
|
+
EntityStore::Store.new.get(@entity.id).name.should eq(name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rspec'
|
3
|
+
require 'hatchet'
|
4
|
+
require 'sequel'
|
5
|
+
|
6
|
+
require "#{Rake.application.original_dir}/lib/entity_store_sequel"
|
7
|
+
|
8
|
+
require_relative '../lib/sequel/core_ext'
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.color_enabled = true
|
12
|
+
end
|
13
|
+
|
14
|
+
include EntityStore
|
15
|
+
include EntityStoreSequel
|
16
|
+
|
17
|
+
Hatchet.configure do |config|
|
18
|
+
config.level :fatal
|
19
|
+
config.formatter = Hatchet::SimpleFormatter.new
|
20
|
+
config.appenders << Hatchet::LoggerAppender.new do |appender|
|
21
|
+
appender.logger = Logger.new(STDOUT)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
include Hatchet
|
25
|
+
|
26
|
+
EntityStore::Config.logger = log
|
27
|
+
|
28
|
+
def random_string
|
29
|
+
(0...24).map{ ('a'..'z').to_a[rand(26)] }.join
|
30
|
+
end
|
31
|
+
|
32
|
+
def random_integer
|
33
|
+
rand(9999)
|
34
|
+
end
|
35
|
+
|
36
|
+
def random_time
|
37
|
+
Time.at(Time.now.to_i - random_integer)
|
38
|
+
end
|
39
|
+
|
40
|
+
def random_object_id
|
41
|
+
BSON::ObjectId.from_time(random_time, :unique => true).to_s
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: entity_store_sequel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Binns
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sequel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sequel_pg
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: entity_store
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pigeon_hole
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.1.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.1.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bson
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.8'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.8'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: hatchet
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.2'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.2'
|
111
|
+
description: Sequel body for Entity Store
|
112
|
+
email: stephen@cronofy.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- lib/entity_store_sequel.rb
|
118
|
+
- lib/entity_store_sequel/postgres_entity_store.rb
|
119
|
+
- lib/entity_store_sequel/version.rb
|
120
|
+
- lib/sequel/core_ext.rb
|
121
|
+
- lib/tasks/entity_store.rake
|
122
|
+
- spec/entity_store_sequel/postgres_entity_store_spec.rb
|
123
|
+
- spec/entity_store_spec.rb
|
124
|
+
- spec/spec_helper.rb
|
125
|
+
homepage: http://github.com/cronofy/entity_store_sequel
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 2.6.6
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
148
|
+
summary: Sequel body for Entity Store
|
149
|
+
test_files:
|
150
|
+
- spec/entity_store_sequel/postgres_entity_store_spec.rb
|
151
|
+
- spec/entity_store_spec.rb
|
152
|
+
- spec/spec_helper.rb
|
153
|
+
has_rdoc:
|