entity_store_sequel 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|