rails_event_store_active_record 1.3.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/lib/rails_event_store_active_record.rb +10 -11
  4. data/lib/rails_event_store_active_record/event.rb +1 -1
  5. data/lib/rails_event_store_active_record/event_repository.rb +44 -48
  6. data/lib/rails_event_store_active_record/event_repository_reader.rb +118 -41
  7. data/lib/rails_event_store_active_record/generators/migration_generator.rb +1 -6
  8. data/lib/rails_event_store_active_record/generators/templates/create_event_store_events_template.rb +15 -10
  9. data/lib/rails_event_store_active_record/index_violation_detector.rb +33 -18
  10. data/lib/rails_event_store_active_record/version.rb +1 -1
  11. data/lib/rails_event_store_active_record/with_abstract_base_class.rb +39 -0
  12. data/lib/rails_event_store_active_record/with_default_models.rb +9 -0
  13. metadata +22 -42
  14. data/CHANGELOG.md +0 -75
  15. data/Gemfile +0 -18
  16. data/Makefile +0 -28
  17. data/bin/console +0 -14
  18. data/bin/setup +0 -7
  19. data/lib/rails_event_store_active_record/generators/binary_data_and_metadata_generator.rb +0 -31
  20. data/lib/rails_event_store_active_record/generators/index_by_event_type_generator.rb +0 -31
  21. data/lib/rails_event_store_active_record/generators/limit_for_event_id_generator.rb +0 -31
  22. data/lib/rails_event_store_active_record/generators/templates/binary_data_and_metadata_template.rb +0 -35
  23. data/lib/rails_event_store_active_record/generators/templates/index_by_event_type_template.rb +0 -7
  24. data/lib/rails_event_store_active_record/generators/templates/limit_for_event_id_template.rb +0 -8
  25. data/rails_event_store_active_record.gemspec +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0deda45046d7c0914a105aa67fe9c694550a7a3c07aec439a80a5b01a2a13418
4
- data.tar.gz: 664c1aa606c495b81081861adca51af9d9829f40cdafaba61b9b73be586fa867
3
+ metadata.gz: c0bef98dccdd36a255c20ef3bd059921c483fe3e9e448bd53c48fa23c6032692
4
+ data.tar.gz: 02f25563e5d185d4d19fbe79e92d83d2c8abe14281797f2d365db970664f464e
5
5
  SHA512:
6
- metadata.gz: ef624e7e400a25baa7a6b8a444c585a0d568673914f15d51a22a910f1152e2239585df0bf8cfe0ecd958b768bb14d2c7813035f5cd80263aebcbfdb307909440
7
- data.tar.gz: 218e460ff03c3efbb924a9a0911a7e82e38d2c7684d430c8b8791d674bdfa1f1a61953386f1008a3a728d5b9918f1de21aacf5d831429bb54328ea93c372d45f
6
+ metadata.gz: 3949e5687ec1647b7257c25cf337f488f012df089226819e4b4198937b72eb8d3d1c1e8d09fbb4cf46711abf583743c49edfd76c00def3f1f5800b555db0fa1e
7
+ data.tar.gz: 5dd00bbb2a01217095c8e5ed4130582e0f8a23b6cb0fdaf6cb8c94f70afe371648197b3f5cbf8a98e0711e529b3ae87c02619a1372be3679f808ee2367e49f26
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # RailsEventStoreActiveRecord
2
2
 
3
- An Active Record based implementation of events repository for [Rails Event Store](https://github.com/RailsEventStore/rails_event_store).
3
+ Persistent event repository implementation for RubyEventStore based on ActiveRecord. Ships with database schema and migrations suitable for PostgreSQL, MySQL ans SQLite database engines.
4
4
 
5
- This is the default repository used in `rails_event_store` gem.
5
+ Includes repository implementation with linearized writes to achieve log-like properties of streams on top of SQL database engine.
6
+
7
+ Find out more at [https://railseventstore.org](https://railseventstore.org/)
@@ -1,13 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails_event_store_active_record/generators/migration_generator'
4
- require 'rails_event_store_active_record/generators/index_by_event_type_generator'
5
- require 'rails_event_store_active_record/generators/limit_for_event_id_generator'
6
- require 'rails_event_store_active_record/generators/binary_data_and_metadata_generator'
7
- require 'rails_event_store_active_record/event'
8
- require 'rails_event_store_active_record/event_repository'
9
- require 'rails_event_store_active_record/batch_enumerator'
10
- require 'rails_event_store_active_record/event_repository_reader'
11
- require 'rails_event_store_active_record/index_violation_detector'
12
- require 'rails_event_store_active_record/pg_linearized_event_repository'
13
- require 'rails_event_store_active_record/version'
3
+ require_relative 'rails_event_store_active_record/generators/migration_generator'
4
+ require_relative 'rails_event_store_active_record/event'
5
+ require_relative 'rails_event_store_active_record/with_default_models'
6
+ require_relative 'rails_event_store_active_record/with_abstract_base_class'
7
+ require_relative 'rails_event_store_active_record/event_repository'
8
+ require_relative 'rails_event_store_active_record/batch_enumerator'
9
+ require_relative 'rails_event_store_active_record/event_repository_reader'
10
+ require_relative 'rails_event_store_active_record/index_violation_detector'
11
+ require_relative 'rails_event_store_active_record/pg_linearized_event_repository'
12
+ require_relative 'rails_event_store_active_record/version'
@@ -11,6 +11,6 @@ module RailsEventStoreActiveRecord
11
11
  class EventInStream < ::ActiveRecord::Base
12
12
  self.primary_key = :id
13
13
  self.table_name = 'event_store_events_in_streams'
14
- belongs_to :event
14
+ belongs_to :event, primary_key: :event_id
15
15
  end
16
16
  end
@@ -6,33 +6,36 @@ require 'activerecord-import'
6
6
  module RailsEventStoreActiveRecord
7
7
  class EventRepository
8
8
  POSITION_SHIFT = 1
9
- SERIALIZED_GLOBAL_STREAM_NAME = "all".freeze
10
9
 
11
- def initialize
12
- @repo_reader = EventRepositoryReader.new
10
+ def initialize(model_factory: WithDefaultModels.new, serializer:)
11
+ @serializer = serializer
12
+
13
+ @event_klass, @stream_klass = model_factory.call
14
+ @repo_reader = EventRepositoryReader.new(@event_klass, @stream_klass, serializer)
15
+ @index_violation_detector = IndexViolationDetector.new(@event_klass.table_name, @stream_klass.table_name)
13
16
  end
14
17
 
15
- def append_to_stream(events, stream, expected_version)
16
- records, event_ids = [], []
17
- Array(events).each do |event|
18
- records << build_event_hash(event)
19
- event_ids << event.event_id
18
+ def append_to_stream(records, stream, expected_version)
19
+ hashes = []
20
+ event_ids = []
21
+ records.each do |record|
22
+ hashes << import_hash(record, record.serialize(serializer))
23
+ event_ids << record.event_id
20
24
  end
21
- add_to_stream(event_ids, stream, expected_version, true) do
22
- Event.import(records)
25
+ add_to_stream(event_ids, stream, expected_version) do
26
+ @event_klass.import(hashes)
23
27
  end
24
28
  end
25
29
 
26
30
  def link_to_stream(event_ids, stream, expected_version)
27
- event_ids = Array(event_ids)
28
- (event_ids - Event.where(id: event_ids).pluck(:id)).each do |id|
31
+ (event_ids - @event_klass.where(event_id: event_ids).pluck(:event_id)).each do |id|
29
32
  raise RubyEventStore::EventNotFound.new(id)
30
33
  end
31
- add_to_stream(event_ids, stream, expected_version, nil)
34
+ add_to_stream(event_ids, stream, expected_version)
32
35
  end
33
36
 
34
37
  def delete_stream(stream)
35
- EventInStream.where(stream: stream.name).delete_all
38
+ @stream_klass.where(stream: stream.name).delete_all
36
39
  end
37
40
 
38
41
  def has_event?(event_id)
@@ -51,49 +54,40 @@ module RailsEventStoreActiveRecord
51
54
  @repo_reader.count(specification)
52
55
  end
53
56
 
54
- def update_messages(messages)
55
- hashes = messages.map(&:to_h)
56
- hashes.each{|h| h[:id] = h.delete(:event_id) }
57
- for_update = messages.map(&:event_id)
57
+ def update_messages(records)
58
+ hashes = records.map { |record| import_hash(record, record.serialize(serializer)) }
59
+ for_update = records.map(&:event_id)
58
60
  start_transaction do
59
- existing = Event.where(id: for_update).pluck(:id)
60
- (for_update - existing).each{|id| raise RubyEventStore::EventNotFound.new(id) }
61
- Event.import(hashes, on_duplicate_key_update: [:data, :metadata, :event_type])
61
+ existing = @event_klass.where(event_id: for_update).pluck(:event_id, :id).to_h
62
+ (for_update - existing.keys).each{|id| raise RubyEventStore::EventNotFound.new(id) }
63
+ hashes.each { |h| h[:id] = existing.fetch(h.fetch(:event_id)) }
64
+ @event_klass.import(hashes, on_duplicate_key_update: [:data, :metadata, :event_type, :valid_at])
62
65
  end
63
66
  end
64
67
 
65
68
  def streams_of(event_id)
66
- EventInStream.where(event_id: event_id)
67
- .where.not(stream: SERIALIZED_GLOBAL_STREAM_NAME)
69
+ @stream_klass.where(event_id: event_id)
68
70
  .pluck(:stream)
69
- .map{|name| RubyEventStore::Stream.new(name)}
71
+ .map { |name| RubyEventStore::Stream.new(name) }
70
72
  end
71
73
 
72
74
  private
75
+ attr_reader :serializer
73
76
 
74
- def add_to_stream(event_ids, stream, expected_version, include_global)
75
- last_stream_version = ->(stream_) { EventInStream.where(stream: stream_.name).order("position DESC").first.try(:position) }
77
+ def add_to_stream(event_ids, stream, expected_version)
78
+ last_stream_version = ->(stream_) { @stream_klass.where(stream: stream_.name).order("position DESC").first.try(:position) }
76
79
  resolved_version = expected_version.resolve_for(stream, last_stream_version)
77
80
 
78
81
  start_transaction do
79
82
  yield if block_given?
80
- in_stream = event_ids.flat_map.with_index do |event_id, index|
81
- position = compute_position(resolved_version, index)
82
- collection = []
83
- collection.unshift({
84
- stream: SERIALIZED_GLOBAL_STREAM_NAME,
85
- position: nil,
86
- event_id: event_id,
87
- }) if include_global
88
- collection.unshift({
83
+ in_stream = event_ids.map.with_index do |event_id, index|
84
+ {
89
85
  stream: stream.name,
90
- position: position,
91
- event_id: event_id
92
- }) unless stream.global?
93
- collection
86
+ position: compute_position(resolved_version, index),
87
+ event_id: event_id,
88
+ }
94
89
  end
95
- fill_ids(in_stream)
96
- EventInStream.import(in_stream)
90
+ @stream_klass.import(in_stream) unless stream.global?
97
91
  end
98
92
  self
99
93
  rescue ActiveRecord::RecordNotUnique => e
@@ -114,24 +108,26 @@ module RailsEventStoreActiveRecord
114
108
  end
115
109
 
116
110
  def detect_index_violated(message)
117
- IndexViolationDetector.new.detect(message)
111
+ @index_violation_detector.detect(message)
118
112
  end
119
113
 
120
- def build_event_hash(serialized_record)
114
+ def import_hash(record, serialized_record)
121
115
  {
122
- id: serialized_record.event_id,
116
+ event_id: serialized_record.event_id,
123
117
  data: serialized_record.data,
124
118
  metadata: serialized_record.metadata,
125
- event_type: serialized_record.event_type
119
+ event_type: serialized_record.event_type,
120
+ created_at: record.timestamp,
121
+ valid_at: optimize_timestamp(record.valid_at, record.timestamp),
126
122
  }
127
123
  end
128
124
 
129
- # Overwritten in a sub-class
130
- def fill_ids(_in_stream)
125
+ def optimize_timestamp(valid_at, created_at)
126
+ valid_at unless valid_at.eql?(created_at)
131
127
  end
132
128
 
133
129
  def start_transaction(&block)
134
- ActiveRecord::Base.transaction(requires_new: true, &block)
130
+ @event_klass.transaction(requires_new: true, &block)
135
131
  end
136
132
  end
137
133
 
@@ -3,92 +3,169 @@
3
3
  module RailsEventStoreActiveRecord
4
4
  class EventRepositoryReader
5
5
 
6
+ def initialize(event_klass, stream_klass, serializer)
7
+ @event_klass = event_klass
8
+ @stream_klass = stream_klass
9
+ @serializer = serializer
10
+ end
11
+
6
12
  def has_event?(event_id)
7
- Event.exists?(id: event_id)
13
+ @event_klass.exists?(event_id: event_id)
8
14
  end
9
15
 
10
16
  def last_stream_event(stream)
11
- record = EventInStream.where(stream: stream.name).order('position DESC, id DESC').first
12
- record && build_serialized_record(record)
17
+ record_ = @stream_klass.where(stream: stream.name).order('position DESC, id DESC').first
18
+ record(record_) if record_
13
19
  end
14
20
 
15
21
  def read(spec)
16
- raise RubyEventStore::ReservedInternalName if spec.stream.name.eql?(EventRepository::SERIALIZED_GLOBAL_STREAM_NAME)
17
-
18
22
  stream = read_scope(spec)
19
-
20
23
  if spec.batched?
21
- batch_reader = ->(offset_id, limit) do
22
- records = offset_id.nil? ? stream.limit(limit) : stream.where(start_offset_condition(spec, offset_id)).limit(limit)
23
- [records.map(&method(:build_serialized_record)), records.last]
24
- end
25
- BatchEnumerator.new(spec.batch_size, spec.limit, batch_reader).each
24
+ spec.time_sort_by ? offset_limit_batch_reader(spec, stream) : monotonic_id_batch_reader(spec, stream)
26
25
  elsif spec.first?
27
- record = stream.first
28
- build_serialized_record(record) if record
26
+ record_ = stream.first
27
+ record(record_) if record_
29
28
  elsif spec.last?
30
- record = stream.last
31
- build_serialized_record(record) if record
29
+ record_ = stream.last
30
+ record(record_) if record_
32
31
  else
33
- stream.map(&method(:build_serialized_record)).each
32
+ stream.map(&method(:record)).each
34
33
  end
35
34
  end
36
35
 
37
36
  def count(spec)
38
- raise RubyEventStore::ReservedInternalName if spec.stream.name.eql?(EventRepository::SERIALIZED_GLOBAL_STREAM_NAME)
39
-
40
37
  read_scope(spec).count
41
38
  end
42
39
 
43
40
  private
41
+ attr_reader :serializer
42
+
43
+ def offset_limit_batch_reader(spec, stream)
44
+ batch_reader = ->(offset, limit) do
45
+ stream
46
+ .offset(offset)
47
+ .limit(limit)
48
+ .map(&method(:record))
49
+ end
50
+ RubyEventStore::BatchEnumerator.new(spec.batch_size, spec.limit, batch_reader).each
51
+ end
52
+
53
+ def monotonic_id_batch_reader(spec, stream)
54
+ batch_reader = ->(offset_id, limit) do
55
+ search_in = spec.stream.global? ? @event_klass.table_name : @stream_klass.table_name
56
+ records = offset_id.nil? ? stream.limit(limit) : stream.where(start_offset_condition(spec, offset_id, search_in)).limit(limit)
57
+ [records.map(&method(:record)), records.last]
58
+ end
59
+ BatchEnumerator.new(spec.batch_size, spec.limit, batch_reader).each
60
+ end
44
61
 
45
62
  def read_scope(spec)
46
- stream = EventInStream.preload(:event).where(stream: normalize_stream_name(spec))
47
- stream = stream.where(event_id: spec.with_ids) if spec.with_ids?
48
- stream = stream.joins(:event).where(event_store_events: {event_type: spec.with_types}) if spec.with_types?
49
- stream = stream.order(position: order(spec)) unless spec.stream.global?
50
- stream = stream.limit(spec.limit) if spec.limit?
51
- stream = stream.where(start_condition(spec)) if spec.start
52
- stream = stream.where(stop_condition(spec)) if spec.stop
53
- stream = stream.order(id: order(spec))
54
- stream
63
+ if spec.stream.global?
64
+ stream = @event_klass
65
+ stream = stream.where(event_id: spec.with_ids) if spec.with_ids?
66
+ stream = stream.where(event_type: spec.with_types) if spec.with_types?
67
+ stream = ordered(stream, spec)
68
+ stream = stream.limit(spec.limit) if spec.limit?
69
+ stream = stream.where(start_condition_in_global_stream(spec)) if spec.start
70
+ stream = stream.where(stop_condition_in_global_stream(spec)) if spec.stop
71
+ stream = stream.where(older_than_condition(spec)) if spec.older_than
72
+ stream = stream.where(older_than_or_equal_condition(spec)) if spec.older_than_or_equal
73
+ stream = stream.where(newer_than_condition(spec)) if spec.newer_than
74
+ stream = stream.where(newer_than_or_equal_condition(spec)) if spec.newer_than_or_equal
75
+ stream.order(id: order(spec))
76
+ else
77
+ stream = @stream_klass.preload(:event).where(stream: spec.stream.name)
78
+ stream = stream.where(event_id: spec.with_ids) if spec.with_ids?
79
+ stream = stream.where(@event_klass.table_name => {event_type: spec.with_types}) if spec.with_types?
80
+ stream = ordered(stream.joins(:event), spec)
81
+ stream = stream.order(position: order(spec), id: order(spec))
82
+ stream = stream.limit(spec.limit) if spec.limit?
83
+ stream = stream.where(start_condition(spec)) if spec.start
84
+ stream = stream.where(stop_condition(spec)) if spec.stop
85
+ stream = stream.where(older_than_condition(spec)) if spec.older_than
86
+ stream = stream.where(older_than_or_equal_condition(spec)) if spec.older_than_or_equal
87
+ stream = stream.where(newer_than_condition(spec)) if spec.newer_than
88
+ stream = stream.where(newer_than_or_equal_condition(spec)) if spec.newer_than_or_equal
89
+ stream
90
+ end
55
91
  end
56
92
 
57
- def normalize_stream_name(specification)
58
- specification.stream.global? ? EventRepository::SERIALIZED_GLOBAL_STREAM_NAME : specification.stream.name
93
+ def ordered(stream, spec)
94
+ case spec.time_sort_by
95
+ when :as_at
96
+ stream.order("#{@event_klass.table_name}.created_at #{order(spec)}")
97
+ when :as_of
98
+ stream.order("#{@event_klass.table_name}.valid_at #{order(spec)}")
99
+ else
100
+ stream
101
+ end
59
102
  end
60
103
 
61
- def start_offset_condition(specification, record_id)
62
- condition = specification.forward? ? 'event_store_events_in_streams.id > ?' : 'event_store_events_in_streams.id < ?'
104
+ def start_offset_condition(specification, record_id, search_in)
105
+ condition = "#{search_in}.id #{specification.forward? ? '>' : '<'} ?"
63
106
  [condition, record_id]
64
107
  end
65
108
 
66
- def stop_offset_condition(specification, record_id)
67
- condition = specification.forward? ? 'event_store_events_in_streams.id < ?' : 'event_store_events_in_streams.id > ?'
109
+ def stop_offset_condition(specification, record_id, search_in)
110
+ condition = "#{search_in}.id #{specification.forward? ? '<' : '>'} ?"
68
111
  [condition, record_id]
69
112
  end
70
113
 
71
114
  def start_condition(specification)
72
115
  start_offset_condition(specification,
73
- EventInStream.find_by!(event_id: specification.start, stream: normalize_stream_name(specification)))
116
+ @stream_klass.find_by!(event_id: specification.start, stream: specification.stream.name),
117
+ @stream_klass.table_name)
74
118
  end
75
119
 
76
120
  def stop_condition(specification)
77
121
  stop_offset_condition(specification,
78
- EventInStream.find_by!(event_id: specification.stop, stream: normalize_stream_name(specification)))
122
+ @stream_klass.find_by!(event_id: specification.stop, stream: specification.stream.name),
123
+ @stream_klass.table_name)
124
+ end
125
+
126
+ def start_condition_in_global_stream(specification)
127
+ start_offset_condition(specification,
128
+ @event_klass.find_by!(event_id: specification.start),
129
+ @event_klass.table_name)
130
+ end
131
+
132
+ def stop_condition_in_global_stream(specification)
133
+ stop_offset_condition(specification,
134
+ @event_klass.find_by!(event_id: specification.stop),
135
+ @event_klass.table_name)
136
+ end
137
+
138
+ def older_than_condition(specification)
139
+ ["#{@event_klass.table_name}.created_at < ?", specification.older_than]
140
+ end
141
+
142
+ def older_than_or_equal_condition(specification)
143
+ ["#{@event_klass.table_name}.created_at <= ?", specification.older_than_or_equal]
144
+ end
145
+
146
+ def newer_than_condition(specification)
147
+ ["#{@event_klass.table_name}.created_at > ?", specification.newer_than]
148
+ end
149
+
150
+ def newer_than_or_equal_condition(specification)
151
+ ["#{@event_klass.table_name}.created_at >= ?", specification.newer_than_or_equal]
79
152
  end
80
153
 
81
154
  def order(spec)
82
155
  spec.forward? ? 'ASC' : 'DESC'
83
156
  end
84
157
 
85
- def build_serialized_record(record)
158
+ def record(record)
159
+ record = record.event if @stream_klass === record
160
+
86
161
  RubyEventStore::SerializedRecord.new(
87
- event_id: record.event.id,
88
- metadata: record.event.metadata,
89
- data: record.event.data,
90
- event_type: record.event.event_type
91
- )
162
+ event_id: record.event_id,
163
+ metadata: record.metadata,
164
+ data: record.data,
165
+ event_type: record.event_type,
166
+ timestamp: record.created_at.iso8601(RubyEventStore::TIMESTAMP_PRECISION),
167
+ valid_at: (record.valid_at || record.created_at).iso8601(RubyEventStore::TIMESTAMP_PRECISION),
168
+ ).deserialize(serializer)
92
169
  end
93
170
  end
94
171
 
@@ -16,7 +16,7 @@ module RailsEventStoreActiveRecord
16
16
  :data_type,
17
17
  type: :string,
18
18
  default: 'binary',
19
- desc: "Configure the data type for `data` and `meta data` feilds in Postgres migration (options: #{DATA_TYPES.join('/')})"
19
+ desc: "Configure the data type for `data` and `meta data` fields in Postgres migration (options: #{DATA_TYPES.join('/')})"
20
20
  )
21
21
 
22
22
  def initialize(*args)
@@ -37,12 +37,7 @@ module RailsEventStoreActiveRecord
37
37
  options.fetch('data_type')
38
38
  end
39
39
 
40
- def rails_version
41
- Rails::VERSION::STRING
42
- end
43
-
44
40
  def migration_version
45
- return nil if Gem::Version.new(rails_version) < Gem::Version.new("5.0.0")
46
41
  "[4.2]"
47
42
  end
48
43
 
@@ -4,8 +4,7 @@ class CreateEventStoreEvents < ActiveRecord::Migration<%= migration_version %>
4
4
  def change
5
5
  postgres = ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
6
6
  sqlite = ActiveRecord::Base.connection.adapter_name == "SQLite"
7
- rails_42 = Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("5.0.0")
8
- enable_extension "pgcrypto" if postgres
7
+
9
8
  create_table(:event_store_events_in_streams, force: false) do |t|
10
9
  t.string :stream, null: false
11
10
  t.integer :position, null: true
@@ -14,32 +13,38 @@ class CreateEventStoreEvents < ActiveRecord::Migration<%= migration_version %>
14
13
  else
15
14
  t.references :event, null: false, type: :string, limit: 36
16
15
  end
17
- t.datetime :created_at, null: false
16
+ if postgres
17
+ t.datetime :created_at, null: false
18
+ else
19
+ t.datetime :created_at, null: false, precision: 6
20
+ end
18
21
  end
19
22
  add_index :event_store_events_in_streams, [:stream, :position], unique: true
20
23
  add_index :event_store_events_in_streams, [:created_at]
21
24
  add_index :event_store_events_in_streams, [:stream, :event_id], unique: true
22
25
 
23
26
  if postgres
24
- create_table(:event_store_events, id: :uuid, default: 'gen_random_uuid()', force: false) do |t|
27
+ create_table(:event_store_events, force: false) do |t|
28
+ t.references :event, null: false, type: :uuid
25
29
  t.string :event_type, null: false
26
30
  t.<%= data_type %> :metadata
27
31
  t.<%= data_type %> :data, null: false
28
32
  t.datetime :created_at, null: false
33
+ t.datetime :valid_at, null: true
29
34
  end
30
35
  else
31
- create_table(:event_store_events, id: false, force: false) do |t|
32
- t.string :id, limit: 36, primary_key: true, null: false
36
+ create_table(:event_store_events, force: false) do |t|
37
+ t.references :event, null: false, type: :string, limit: 36
33
38
  t.string :event_type, null: false
34
39
  t.binary :metadata
35
40
  t.binary :data, null: false
36
- t.datetime :created_at, null: false
37
- end
38
- if sqlite && rails_42
39
- add_index :event_store_events, :id, unique: true
41
+ t.datetime :created_at, null: false, precision: 6
42
+ t.datetime :valid_at, null: true, precision: 6
40
43
  end
41
44
  end
45
+ add_index :event_store_events, :event_id, unique: true
42
46
  add_index :event_store_events, :created_at
47
+ add_index :event_store_events, :valid_at
43
48
  add_index :event_store_events, :event_type
44
49
  end
45
50
  end
@@ -2,28 +2,43 @@
2
2
 
3
3
  module RailsEventStoreActiveRecord
4
4
  class IndexViolationDetector
5
- MYSQL5_PKEY_ERROR = "for key 'PRIMARY'".freeze
6
- MYSQL8_PKEY_ERROR = "for key 'event_store_events.PRIMARY'".freeze
7
- POSTGRES_PKEY_ERROR = 'event_store_events_pkey'.freeze
8
- SQLITE3_PKEY_ERROR = 'event_store_events.id'.freeze
9
5
 
10
- MYSQL5_INDEX_ERROR = "for key 'index_event_store_events_in_streams_on_stream_and_event_id'".freeze
11
- MYSQL8_INDEX_ERROR = "for key 'event_store_events_in_streams.index_event_store_events_in_streams_on_stream_and_event_id'".freeze
12
- POSTGRES_INDEX_ERROR = 'Key (stream, event_id)'.freeze
13
- SQLITE3_INDEX_ERROR = 'event_store_events_in_streams.stream, event_store_events_in_streams.event_id'.freeze
6
+ def initialize(event_store_events, event_store_events_in_streams)
7
+ @postgres_pkey_error = "Key (event_id)".freeze
8
+ @postgres_index_error = "Key (stream, event_id)".freeze
9
+ @mysql5_pkey_error = "for key 'index_#{event_store_events}_on_event_id'".freeze
10
+ @mysql8_pkey_error = "for key '#{event_store_events}.index_#{event_store_events}_on_event_id'".freeze
11
+ @mysql5_index_error = "for key 'index_#{event_store_events_in_streams}_on_stream_and_event_id'".freeze
12
+ @mysql8_index_error = "for key '#{event_store_events_in_streams}.index_#{event_store_events_in_streams}_on_stream_and_event_id'".freeze
13
+ @sqlite3_pkey_error = "constraint failed: #{event_store_events}.event_id".freeze
14
+ @sqlite3_index_error = "constraint failed: #{event_store_events_in_streams}.stream, #{event_store_events_in_streams}.event_id".freeze
15
+ end
14
16
 
15
17
  def detect(message)
16
- message.include?(MYSQL5_PKEY_ERROR) ||
17
- message.include?(MYSQL8_PKEY_ERROR) ||
18
- message.include?(POSTGRES_PKEY_ERROR) ||
19
- message.include?(SQLITE3_PKEY_ERROR) ||
20
-
21
- message.include?(MYSQL5_INDEX_ERROR) ||
22
- message.include?(MYSQL8_INDEX_ERROR) ||
23
- message.include?(POSTGRES_INDEX_ERROR) ||
24
- message.include?(SQLITE3_INDEX_ERROR)
18
+ detect_postgres(message) ||
19
+ detect_mysql(message) ||
20
+ detect_sqlite(message)
21
+ end
22
+
23
+ private
24
+
25
+ def detect_postgres(message)
26
+ message.include?(@postgres_pkey_error) ||
27
+ message.include?(@postgres_index_error)
28
+ end
29
+
30
+ def detect_mysql(message)
31
+ message.include?(@mysql5_pkey_error) ||
32
+ message.include?(@mysql8_pkey_error) ||
33
+ message.include?(@mysql5_index_error) ||
34
+ message.include?(@mysql8_index_error)
35
+ end
36
+
37
+ def detect_sqlite(message)
38
+ message.include?(@sqlite3_pkey_error) ||
39
+ message.include?(@sqlite3_index_error)
25
40
  end
26
41
  end
27
42
 
28
43
  private_constant(:IndexViolationDetector)
29
- end
44
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsEventStoreActiveRecord
4
- VERSION = "1.3.0"
4
+ VERSION = "2.2.0"
5
5
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsEventStoreActiveRecord
4
+ class WithAbstractBaseClass
5
+ def initialize(base_klass)
6
+ raise ArgumentError.new(
7
+ "#{base_klass} must be an abstract class that inherits from ActiveRecord::Base"
8
+ ) unless base_klass < ActiveRecord::Base && base_klass.abstract_class?
9
+ @base_klass = base_klass
10
+ end
11
+
12
+ def call(instance_id: SecureRandom.hex)
13
+ [
14
+ build_event_klass(instance_id),
15
+ build_stream_klass(instance_id),
16
+ ]
17
+ end
18
+
19
+ private
20
+ def build_event_klass(instance_id)
21
+ Object.const_set("Event_#{instance_id}",
22
+ Class.new(@base_klass) do
23
+ self.primary_key = :id
24
+ self.table_name = 'event_store_events'
25
+ end
26
+ )
27
+ end
28
+
29
+ def build_stream_klass(instance_id)
30
+ Object.const_set("EventInStream_#{instance_id}",
31
+ Class.new(@base_klass) do
32
+ self.primary_key = :id
33
+ self.table_name = 'event_store_events_in_streams'
34
+ belongs_to :event, primary_key: :event_id, class_name: "Event_#{instance_id}"
35
+ end
36
+ )
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsEventStoreActiveRecord
4
+ class WithDefaultModels
5
+ def call
6
+ [Event, EventInStream]
7
+ end
8
+ end
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_event_store_active_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arkency
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-15 00:00:00.000000000 Z
11
+ date: 2021-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby_event_store
@@ -16,42 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 1.3.0
19
+ version: 2.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 1.3.0
26
+ version: 2.2.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: activesupport
28
+ name: activerecord
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '3.0'
33
+ version: '5.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '3.0'
41
- - !ruby/object:Gem::Dependency
42
- name: activemodel
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '3.0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '3.0'
40
+ version: '5.0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: activerecord-import
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,42 +52,36 @@ dependencies:
66
52
  - - ">="
67
53
  - !ruby/object:Gem::Version
68
54
  version: 1.0.2
69
- description: Implementation of events repository based on Rails Active Record for
70
- Rails Event Store
71
- email:
72
- - dev@arkency.com
55
+ description: |
56
+ Persistent event repository implementation for RubyEventStore based on ActiveRecord. Ships with database schema
57
+ and migrations suitable for PostgreSQL, MySQL ans SQLite database engines.
58
+
59
+ Includes repository implementation with linearized writes to achieve log-like properties of streams
60
+ on top of SQL database engine.
61
+ email: dev@arkency.com
73
62
  executables: []
74
63
  extensions: []
75
- extra_rdoc_files: []
64
+ extra_rdoc_files:
65
+ - README.md
76
66
  files:
77
- - CHANGELOG.md
78
- - Gemfile
79
- - Makefile
80
67
  - README.md
81
- - bin/console
82
- - bin/setup
83
68
  - lib/rails_event_store_active_record.rb
84
69
  - lib/rails_event_store_active_record/batch_enumerator.rb
85
70
  - lib/rails_event_store_active_record/event.rb
86
71
  - lib/rails_event_store_active_record/event_repository.rb
87
72
  - lib/rails_event_store_active_record/event_repository_reader.rb
88
- - lib/rails_event_store_active_record/generators/binary_data_and_metadata_generator.rb
89
- - lib/rails_event_store_active_record/generators/index_by_event_type_generator.rb
90
- - lib/rails_event_store_active_record/generators/limit_for_event_id_generator.rb
91
73
  - lib/rails_event_store_active_record/generators/migration_generator.rb
92
- - lib/rails_event_store_active_record/generators/templates/binary_data_and_metadata_template.rb
93
74
  - lib/rails_event_store_active_record/generators/templates/create_event_store_events_template.rb
94
- - lib/rails_event_store_active_record/generators/templates/index_by_event_type_template.rb
95
- - lib/rails_event_store_active_record/generators/templates/limit_for_event_id_template.rb
96
75
  - lib/rails_event_store_active_record/index_violation_detector.rb
97
76
  - lib/rails_event_store_active_record/pg_linearized_event_repository.rb
98
77
  - lib/rails_event_store_active_record/version.rb
99
- - rails_event_store_active_record.gemspec
78
+ - lib/rails_event_store_active_record/with_abstract_base_class.rb
79
+ - lib/rails_event_store_active_record/with_default_models.rb
100
80
  homepage: https://railseventstore.org
101
81
  licenses:
102
82
  - MIT
103
83
  metadata:
104
- homepage_uri: https://railseventstore.org/
84
+ homepage_uri: https://railseventstore.org
105
85
  changelog_uri: https://github.com/RailsEventStore/rails_event_store/releases
106
86
  source_code_uri: https://github.com/RailsEventStore/rails_event_store
107
87
  bug_tracker_uri: https://github.com/RailsEventStore/rails_event_store/issues
@@ -113,7 +93,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
93
  requirements:
114
94
  - - ">="
115
95
  - !ruby/object:Gem::Version
116
- version: '0'
96
+ version: '2.6'
117
97
  required_rubygems_version: !ruby/object:Gem::Requirement
118
98
  requirements:
119
99
  - - ">="
@@ -123,5 +103,5 @@ requirements: []
123
103
  rubygems_version: 3.1.4
124
104
  signing_key:
125
105
  specification_version: 4
126
- summary: Active Record events repository for Rails Event Store
106
+ summary: Persistent event repository implementation for RubyEventStore based on ActiveRecord
127
107
  test_files: []
data/CHANGELOG.md DELETED
@@ -1,75 +0,0 @@
1
- Further changes can be tracked at [releases page](https://github.com/RailsEventStore/rails_event_store/releases).
2
-
3
- ### 0.6.14 (unreleased)
4
-
5
- * Run tests in random order
6
-
7
- ### 0.6.13 (24.08.2017)
8
-
9
- * Fix: Generate migration with version number for Rails versions that support it. Fixes compatibility with Rails 5.1.
10
-
11
- ### 0.6.12 (21.08.2017)
12
-
13
- * ruby_event_store updated to 0.14.0
14
-
15
- ### 0.6.11 (8.02.2016)
16
-
17
- * Fix: Explicit order when querying forward. Leaving it implcit to database engine choice gives different results on different engines.
18
-
19
- ### 0.6.10 (23.11.2016)
20
-
21
- * Change: requires update to allow void active_record dependency when using RailsEventStore without RailsEventStoreActiveRecord
22
-
23
- ### 0.6.9 (18.10.2016)
24
-
25
- * ruby_event_store updated to 0.13.0
26
-
27
- ### 0.6.8 (11.08.2016)
28
-
29
- * ruby_event_store updated to 0.12.1
30
- * make this gem mutant free - 100% mutation tests coverage
31
-
32
- ### 0.6.7 (10.08.2016)
33
-
34
- * ruby_event_store updated to 0.12.0
35
-
36
- ### 0.6.6 (12.07.2016)
37
-
38
- * ruby_event_store updated to 0.11.0
39
-
40
- ### 0.6.5 (12.07.2016)
41
-
42
- * ruby_event_store updated to 0.10.1
43
- * Fix: fixed bug which have made repository unable to load a event with associated data or metadata. Tests for this bug were added in ruby_event_store 0.10.1
44
-
45
- ### 0.6.4 (12.07.2016)
46
-
47
- * ruby_event_store updated to 0.10.0
48
-
49
- ### 0.6.3 (24.06.2016)
50
-
51
- * Change: ruby_event_store updated to 0.9.0 (Call instead of handle_event)
52
- * Fix: Clarify Licensing information
53
-
54
- ### 0.6.2 (21.06.2016)
55
-
56
- * ruby_event_store updated to 0.8.0
57
-
58
- ### 0.6.1 (21.06.2016)
59
-
60
- * ruby_event_store updated to 0.7.0
61
- * add indexes for commonly searched fields: time and type to migration template PR #6
62
-
63
- ### 0.6.0 (25.05.2016)
64
-
65
- * ruby_event_store updated to 0.6.0
66
-
67
- ### 0.5.1 (11.04.2016)
68
-
69
- * Change: Rename migration generator from 'migrate' to 'migration' PR #3
70
- * Change: Allow to provide a custom event class #2
71
-
72
-
73
- ### 0.5.0 (25.03.2016)
74
-
75
- * Code moved from RailsEventStore 0.5.0
data/Gemfile DELETED
@@ -1,18 +0,0 @@
1
- source 'https://rubygems.org'
2
- git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
- gemspec
4
-
5
- eval_gemfile File.expand_path('../support/bundler/Gemfile.shared', __dir__)
6
-
7
- gem 'ruby_event_store', path: '../ruby_event_store'
8
- gem 'pg', '1.2.2'
9
- gem 'mysql2', '0.5.3'
10
- gem 'fakefs', '~> 0.11.2'
11
- gem 'childprocess'
12
- gem 'rails', ENV['RAILS_VERSION']
13
-
14
- if Gem::Version.new(ENV['RAILS_VERSION']) >= Gem::Version.new('6.0.0')
15
- gem 'sqlite3', '1.4.2'
16
- else
17
- gem 'sqlite3', '1.3.13'
18
- end
data/Makefile DELETED
@@ -1,28 +0,0 @@
1
- GEM_VERSION = $(shell cat ../RES_VERSION)
2
- GEM_NAME = rails_event_store_active_record
3
- REQUIRE = $(GEM_NAME)
4
- IGNORE = RailsEventStoreActiveRecord::IndexViolationDetector\#detect \
5
- RailsEventStoreActiveRecord::PgLinearizedEventRepository* \
6
- RailsEventStoreActiveRecord::EventRepository\#update_messages
7
- SUBJECT ?= RailsEventStoreActiveRecord*
8
- DATABASE_URL ?= sqlite3::memory:
9
-
10
- include ../support/make/install.mk
11
- include ../support/make/test.mk
12
- include ../support/make/mutant.mk
13
- include ../support/make/gem.mk
14
- include ../support/make/help.mk
15
-
16
- install: install-gemfiles
17
-
18
- remove-lock: remove-lockfiles
19
-
20
- install-gemfiles:
21
- @BUNDLE_GEMFILE=../support/bundler/Gemfile.0_33_0 bundle check || BUNDLE_GEMFILE=../support/bundler/Gemfile.0_33_0 bundle install
22
- @BUNDLE_GEMFILE=../support/bundler/Gemfile.0_34_0 bundle check || BUNDLE_GEMFILE=../support/bundler/Gemfile.0_34_0 bundle install
23
- @BUNDLE_GEMFILE=../support/bundler/Gemfile.0_35_0 bundle check || BUNDLE_GEMFILE=../support/bundler/Gemfile.0_35_0 bundle install
24
-
25
- remove-lockfiles:
26
- -rm ../support/bundler/Gemfile.0_33_0.lock
27
- -rm ../support/bundler/Gemfile.0_34_0.lock
28
- -rm ../support/bundler/Gemfile.0_35_0.lock
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "rails_event_store_active_record"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start
data/bin/setup DELETED
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
-
5
- bundle install
6
-
7
- # Do any other automated setup that you need to do here
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- begin
4
- require 'rails/generators'
5
- rescue LoadError
6
- end
7
-
8
- module RailsEventStoreActiveRecord
9
- class BinaryDataAndMetadataGenerator < Rails::Generators::Base
10
- source_root File.expand_path(File.join(File.dirname(__FILE__), '../generators/templates'))
11
-
12
- def create_migration
13
- template "binary_data_and_metadata_template.rb", "db/migrate/#{timestamp}_binary_data_and_metadata.rb"
14
- end
15
-
16
- private
17
-
18
- def rails_version
19
- Rails::VERSION::STRING
20
- end
21
-
22
- def migration_version
23
- return nil if Gem::Version.new(rails_version) < Gem::Version.new("5.0.0")
24
- "[4.2]"
25
- end
26
-
27
- def timestamp
28
- Time.now.strftime("%Y%m%d%H%M%S")
29
- end
30
- end
31
- end if defined?(Rails::Generators::Base)
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- begin
4
- require 'rails/generators'
5
- rescue LoadError
6
- end
7
-
8
- module RailsEventStoreActiveRecord
9
- class IndexByEventTypeGenerator < Rails::Generators::Base
10
- source_root File.expand_path(File.join(File.dirname(__FILE__), '../generators/templates'))
11
-
12
- def create_migration
13
- template "index_by_event_type_template.rb", "db/migrate/#{timestamp}_index_by_event_type.rb"
14
- end
15
-
16
- private
17
-
18
- def rails_version
19
- Rails::VERSION::STRING
20
- end
21
-
22
- def migration_version
23
- return nil if Gem::Version.new(rails_version) < Gem::Version.new("5.0.0")
24
- "[4.2]"
25
- end
26
-
27
- def timestamp
28
- Time.now.strftime("%Y%m%d%H%M%S")
29
- end
30
- end
31
- end if defined?(Rails::Generators::Base)
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- begin
4
- require 'rails/generators'
5
- rescue LoadError
6
- end
7
-
8
- module RailsEventStoreActiveRecord
9
- class LimitForEventIdGenerator < Rails::Generators::Base
10
- source_root File.expand_path(File.join(File.dirname(__FILE__), '../generators/templates'))
11
-
12
- def create_migration
13
- template "limit_for_event_id_template.rb", "db/migrate/#{timestamp}_limit_for_event_id.rb"
14
- end
15
-
16
- private
17
-
18
- def rails_version
19
- Rails::VERSION::STRING
20
- end
21
-
22
- def migration_version
23
- return nil if Gem::Version.new(rails_version) < Gem::Version.new("5.0.0")
24
- "[4.2]"
25
- end
26
-
27
- def timestamp
28
- Time.now.strftime("%Y%m%d%H%M%S")
29
- end
30
- end
31
- end if defined?(Rails::Generators::Base)
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BinaryDataAndMetadata < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- rails_42 = Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("5.0.0")
6
-
7
- case ActiveRecord::Base.connection.adapter_name
8
- when "SQLite"
9
- rename_table :event_store_events, :old_event_store_events
10
- create_table(:event_store_events, id: false, force: false) do |t|
11
- t.string :id, limit: 36, primary_key: true, null: false
12
- t.string :event_type, null: false
13
- t.binary :metadata
14
- t.binary :data, null: false
15
- t.datetime :created_at, null: false
16
- end
17
- add_index :event_store_events, :id, unique: true if rails_42
18
- add_index :event_store_events, :created_at
19
- add_index :event_store_events, :event_type
20
- execute <<-SQL
21
- INSERT INTO event_store_events(id, event_type, metadata, data, created_at)
22
- SELECT id, event_type, metadata, data, created_at FROM old_event_store_events;
23
- SQL
24
- drop_table :old_event_store_events
25
- when "PostgreSQL"
26
- execute <<-SQL
27
- ALTER TABLE event_store_events ALTER COLUMN data TYPE bytea USING convert_to(data, 'UTF8');
28
- ALTER TABLE event_store_events ALTER COLUMN metadata TYPE bytea USING convert_to(metadata, 'UTF8');
29
- SQL
30
- else
31
- change_column :event_store_events, :data, :binary
32
- change_column :event_store_events, :metadata, :binary
33
- end
34
- end
35
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class IndexByEventType < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- add_index :event_store_events, :event_type unless index_exists? :event_store_events, :event_type
6
- end
7
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LimitForEventId < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- postgres = ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
6
- change_column(:event_store_events_in_streams, :event_id, :string, limit: 36) unless postgres
7
- end
8
- end
@@ -1,32 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'rails_event_store_active_record/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = 'rails_event_store_active_record'
8
- spec.version = RailsEventStoreActiveRecord::VERSION
9
- spec.licenses = ['MIT']
10
- spec.authors = ['Arkency']
11
- spec.email = ['dev@arkency.com']
12
-
13
- spec.summary = %q{Active Record events repository for Rails Event Store}
14
- spec.description = %q{Implementation of events repository based on Rails Active Record for Rails Event Store}
15
- spec.homepage = 'https://railseventstore.org'
16
- spec.metadata = {
17
- "homepage_uri" => "https://railseventstore.org/",
18
- "changelog_uri" => "https://github.com/RailsEventStore/rails_event_store/releases",
19
- "source_code_uri" => "https://github.com/RailsEventStore/rails_event_store",
20
- "bug_tracker_uri" => "https://github.com/RailsEventStore/rails_event_store/issues",
21
- }
22
-
23
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
- spec.bindir = 'exe'
25
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
- spec.require_paths = ['lib']
27
-
28
- spec.add_dependency 'ruby_event_store', '= 1.3.0'
29
- spec.add_dependency 'activesupport', '>= 3.0'
30
- spec.add_dependency 'activemodel', '>= 3.0'
31
- spec.add_dependency 'activerecord-import', '>= 1.0.2'
32
- end