sequent 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequent +31 -25
  3. data/lib/notices.rb +2 -0
  4. data/lib/sequent/application_record.rb +2 -0
  5. data/lib/sequent/configuration.rb +24 -31
  6. data/lib/sequent/core/aggregate_repository.rb +17 -13
  7. data/lib/sequent/core/aggregate_root.rb +16 -7
  8. data/lib/sequent/core/aggregate_roots.rb +24 -0
  9. data/lib/sequent/core/aggregate_snapshotter.rb +8 -5
  10. data/lib/sequent/core/base_command_handler.rb +4 -2
  11. data/lib/sequent/core/command.rb +17 -9
  12. data/lib/sequent/core/command_record.rb +8 -3
  13. data/lib/sequent/core/command_service.rb +18 -18
  14. data/lib/sequent/core/core.rb +2 -0
  15. data/lib/sequent/core/current_event.rb +2 -0
  16. data/lib/sequent/core/event.rb +16 -11
  17. data/lib/sequent/core/event_publisher.rb +16 -15
  18. data/lib/sequent/core/event_record.rb +7 -7
  19. data/lib/sequent/core/event_store.rb +57 -50
  20. data/lib/sequent/core/ext/ext.rb +9 -1
  21. data/lib/sequent/core/helpers/array_with_type.rb +4 -1
  22. data/lib/sequent/core/helpers/association_validator.rb +9 -7
  23. data/lib/sequent/core/helpers/attribute_support.rb +45 -28
  24. data/lib/sequent/core/helpers/autoset_attributes.rb +4 -4
  25. data/lib/sequent/core/helpers/boolean_validator.rb +6 -1
  26. data/lib/sequent/core/helpers/copyable.rb +2 -2
  27. data/lib/sequent/core/helpers/date_time_validator.rb +4 -1
  28. data/lib/sequent/core/helpers/date_validator.rb +6 -1
  29. data/lib/sequent/core/helpers/default_validators.rb +12 -10
  30. data/lib/sequent/core/helpers/equal_support.rb +8 -6
  31. data/lib/sequent/core/helpers/helpers.rb +2 -0
  32. data/lib/sequent/core/helpers/mergable.rb +6 -5
  33. data/lib/sequent/core/helpers/message_handler.rb +3 -1
  34. data/lib/sequent/core/helpers/param_support.rb +19 -15
  35. data/lib/sequent/core/helpers/secret.rb +14 -12
  36. data/lib/sequent/core/helpers/string_support.rb +5 -4
  37. data/lib/sequent/core/helpers/string_to_value_parsers.rb +7 -2
  38. data/lib/sequent/core/helpers/string_validator.rb +6 -1
  39. data/lib/sequent/core/helpers/type_conversion_support.rb +5 -3
  40. data/lib/sequent/core/helpers/uuid_helper.rb +5 -2
  41. data/lib/sequent/core/helpers/value_validators.rb +23 -9
  42. data/lib/sequent/core/persistors/active_record_persistor.rb +19 -9
  43. data/lib/sequent/core/persistors/persistor.rb +16 -14
  44. data/lib/sequent/core/persistors/persistors.rb +2 -0
  45. data/lib/sequent/core/persistors/replay_optimized_postgres_persistor.rb +70 -47
  46. data/lib/sequent/core/projector.rb +25 -22
  47. data/lib/sequent/core/random_uuid_generator.rb +2 -0
  48. data/lib/sequent/core/sequent_oj.rb +2 -0
  49. data/lib/sequent/core/stream_record.rb +9 -3
  50. data/lib/sequent/core/transactions/active_record_transaction_provider.rb +5 -9
  51. data/lib/sequent/core/transactions/no_transactions.rb +2 -1
  52. data/lib/sequent/core/transactions/transactions.rb +2 -0
  53. data/lib/sequent/core/value_object.rb +8 -10
  54. data/lib/sequent/core/workflow.rb +7 -5
  55. data/lib/sequent/generator/aggregate.rb +16 -10
  56. data/lib/sequent/generator/command.rb +26 -19
  57. data/lib/sequent/generator/event.rb +19 -17
  58. data/lib/sequent/generator/generator.rb +2 -0
  59. data/lib/sequent/generator/project.rb +2 -0
  60. data/lib/sequent/generator/template_project/Gemfile +1 -1
  61. data/lib/sequent/generator.rb +2 -0
  62. data/lib/sequent/migrations/executor.rb +22 -13
  63. data/lib/sequent/migrations/functions.rb +5 -6
  64. data/lib/sequent/migrations/migrate_events.rb +12 -9
  65. data/lib/sequent/migrations/migrations.rb +2 -1
  66. data/lib/sequent/migrations/planner.rb +33 -23
  67. data/lib/sequent/migrations/projectors.rb +4 -3
  68. data/lib/sequent/migrations/sql.rb +2 -0
  69. data/lib/sequent/migrations/view_schema.rb +84 -45
  70. data/lib/sequent/rake/migration_tasks.rb +58 -22
  71. data/lib/sequent/rake/tasks.rb +5 -2
  72. data/lib/sequent/sequent.rb +2 -0
  73. data/lib/sequent/support/database.rb +30 -15
  74. data/lib/sequent/support/view_projection.rb +6 -3
  75. data/lib/sequent/support/view_schema.rb +2 -0
  76. data/lib/sequent/support.rb +2 -0
  77. data/lib/sequent/test/command_handler_helpers.rb +35 -17
  78. data/lib/sequent/test/event_handler_helpers.rb +10 -4
  79. data/lib/sequent/test/event_stream_helpers.rb +7 -3
  80. data/lib/sequent/test/time_comparison.rb +12 -5
  81. data/lib/sequent/test.rb +2 -0
  82. data/lib/sequent/util/dry_run.rb +11 -8
  83. data/lib/sequent/util/printer.rb +6 -5
  84. data/lib/sequent/util/skip_if_already_processing.rb +3 -1
  85. data/lib/sequent/util/timer.rb +2 -0
  86. data/lib/sequent/util/util.rb +2 -0
  87. data/lib/sequent.rb +2 -0
  88. data/lib/version.rb +3 -1
  89. metadata +81 -66
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
  require_relative 'value_validators'
3
5
 
@@ -18,7 +20,10 @@ module Sequent
18
20
  # They will be converted to `true`, `false` or `nil`
19
21
  class BooleanValidator < ActiveModel::EachValidator
20
22
  def validate_each(subject, attribute, value)
21
- subject.errors.add attribute, :invalid_boolean unless Sequent::Core::Helpers::ValueValidators.for(Boolean).valid_value?(value)
23
+ unless Sequent::Core::Helpers::ValueValidators.for(Boolean).valid_value?(value)
24
+ subject.errors.add attribute,
25
+ :invalid_boolean
26
+ end
22
27
  end
23
28
  end
24
29
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  module Helpers
@@ -17,9 +19,7 @@ module Sequent
17
19
  end
18
20
  the_copy
19
21
  end
20
-
21
22
  end
22
23
  end
23
24
  end
24
25
  end
25
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
 
3
5
  module Sequent
@@ -10,8 +12,9 @@ module Sequent
10
12
  class DateTimeValidator < ActiveModel::EachValidator
11
13
  def validate_each(subject, attribute, value)
12
14
  return if value.is_a?(DateTime)
15
+
13
16
  DateTime.deserialize_from_json(value)
14
- rescue
17
+ rescue StandardError
15
18
  subject.errors.add attribute, :invalid_date_time
16
19
  end
17
20
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
  require_relative 'value_validators'
3
5
 
@@ -10,7 +12,10 @@ module Sequent
10
12
  # attrs value: Date
11
13
  class DateValidator < ActiveModel::EachValidator
12
14
  def validate_each(subject, attribute, value)
13
- subject.errors.add attribute, :invalid_date unless Sequent::Core::Helpers::ValueValidators.for(Date).valid_value?(value)
15
+ unless Sequent::Core::Helpers::ValueValidators.for(Date).valid_value?(value)
16
+ subject.errors.add attribute,
17
+ :invalid_date
18
+ end
14
19
  end
15
20
  end
16
21
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'string_validator'
2
4
  require_relative 'boolean_validator'
3
5
  require_relative 'date_time_validator'
@@ -13,18 +15,18 @@ module Sequent
13
15
  klass.validates_numericality_of field, only_integer: true, allow_nil: true, allow_blank: true
14
16
  end,
15
17
  Date => ->(klass, field) do
16
- klass.validates field, "sequent::Core::Helpers::Date" => true
18
+ klass.validates field, 'sequent::Core::Helpers::Date' => true
17
19
  end,
18
20
  DateTime => ->(klass, field) do
19
- klass.validates field, "sequent::Core::Helpers::DateTime" => true
21
+ klass.validates field, 'sequent::Core::Helpers::DateTime' => true
20
22
  end,
21
- Boolean => -> (klass, field) do
22
- klass.validates field, "sequent::Core::Helpers::Boolean" => true
23
+ Boolean => ->(klass, field) do
24
+ klass.validates field, 'sequent::Core::Helpers::Boolean' => true
23
25
  end,
24
- String => -> (klass, field) do
25
- klass.validates field, "sequent::Core::Helpers::String" => true
26
+ String => ->(klass, field) do
27
+ klass.validates field, 'sequent::Core::Helpers::String' => true
26
28
  end,
27
- Sequent::Core::Helpers::Secret => -> (klass, field) do
29
+ Sequent::Core::Helpers::Secret => ->(klass, field) do
28
30
  klass.after_validation do |object|
29
31
  if object.errors&.any?
30
32
  object.send("#{field}=", nil)
@@ -33,8 +35,8 @@ module Sequent
33
35
  object.send("#{field}=", Sequent::Secret.new(raw_value)) if raw_value
34
36
  end
35
37
  end
36
- end
37
- }
38
+ end,
39
+ }.freeze
38
40
 
39
41
  def self.for(type)
40
42
  new(type)
@@ -46,7 +48,7 @@ module Sequent
46
48
 
47
49
  def add_validations_for(klass, field)
48
50
  validator = VALIDATORS[@type]
49
- validator.call(klass, field) if validator
51
+ validator&.call(klass, field)
50
52
  end
51
53
  end
52
54
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  module Helpers
@@ -8,16 +10,17 @@ module Sequent
8
10
  #
9
11
  module EqualSupport
10
12
  def ==(other)
11
- return false if other == nil
13
+ return false if other.nil?
12
14
  return false if self.class != other.class
15
+
13
16
  self.class.types.each do |name, _|
14
- self_value = self.send(name)
17
+ self_value = send(name)
15
18
  other_value = other.send(name)
16
19
  if self_value.class == DateTime && other_value.class == DateTime
17
20
  # we don't care about milliseconds. If you know a better way of checking for equality please improve.
18
- return false unless (self_value.iso8601 == other_value.iso8601)
21
+ return false unless self_value.iso8601 == other_value.iso8601
19
22
  else
20
- return false unless (self_value == other_value)
23
+ return false unless self_value == other_value
21
24
  end
22
25
  end
23
26
  true
@@ -26,7 +29,7 @@ module Sequent
26
29
  def hash
27
30
  hash = 17
28
31
  self.class.types.each do |name, _|
29
- hash = hash * 31 + self.send(name).hash
32
+ hash = hash * 31 + send(name).hash
30
33
  end
31
34
  hash
32
35
  end
@@ -35,7 +38,6 @@ module Sequent
35
38
  self == other
36
39
  end
37
40
  end
38
-
39
41
  end
40
42
  end
41
43
  end
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dir["#{File.dirname(__FILE__)}/*rb"].each { |f| require_relative f }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  module Helpers
@@ -6,17 +8,16 @@ module Sequent
6
8
  # ben = Person.new(name: 'Ben').merge!(name: 'Ben Vonk')
7
9
  #
8
10
  module Mergable
9
-
10
11
  def merge!(attrs = {})
11
- warn "[DEPRECATION] `merge!` is deprecated. Please use `copy` instead. This method will no longer be included in the next version of Sequent. You can still use it but you will have to include the module `Sequent::Core::Helpers::Mergable` yourself."
12
+ warn <<~EOS
13
+ [DEPRECATION] `merge!` is deprecated. Please use `copy` instead. This method will no longer be included in the next version of Sequent. You can still use it but you will have to include the module `Sequent::Core::Helpers::Mergable` yourself.
14
+ EOS
12
15
  attrs.each do |name, value|
13
- self.send("#{name}=", value)
16
+ send("#{name}=", value)
14
17
  end
15
18
  self
16
19
  end
17
-
18
20
  end
19
21
  end
20
22
  end
21
23
  end
22
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  module Helpers
@@ -56,7 +58,7 @@ module Sequent
56
58
 
57
59
  def handle_message(message)
58
60
  handlers = self.class.message_mapping[message.class]
59
- handlers.each { |handler| self.instance_exec(message, &handler) } if handlers
61
+ handlers&.each { |handler| instance_exec(message, &handler) }
60
62
  end
61
63
  end
62
64
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support'
2
4
 
3
5
  module Sequent
@@ -21,7 +23,6 @@ module Sequent
21
23
  def from_form_data(params = {})
22
24
  from_params(params, false)
23
25
  end
24
-
25
26
  end
26
27
 
27
28
  # extend host class with class methods when we're included
@@ -35,7 +36,8 @@ module Sequent
35
36
  value = params[attribute]
36
37
 
37
38
  next if strict_nil_check && value.nil?
38
- next if (!strict_nil_check && value.blank?)
39
+ next if !strict_nil_check && value.blank?
40
+
39
41
  if type.respond_to? :from_params
40
42
  value = type.from_params(value)
41
43
  elsif value.is_a?(Array)
@@ -58,10 +60,12 @@ module Sequent
58
60
  def as_params
59
61
  hash = HashWithIndifferentAccess.new
60
62
  self.class.types.each do |field|
61
- value = self.instance_variable_get("@#{field[0]}")
62
- next if field[0] == "errors"
63
- hash[field[0]] = if value.kind_of?(Array)
63
+ value = instance_variable_get("@#{field[0]}")
64
+ next if field[0] == 'errors'
65
+
66
+ hash[field[0]] = if value.is_a?(Array)
64
67
  next if value.blank?
68
+
65
69
  value.map { |v| value_to_string(v) }
66
70
  else
67
71
  value_to_string(value)
@@ -86,16 +90,16 @@ module Sequent
86
90
 
87
91
  def make_params(key, enumerable, memo = {})
88
92
  case enumerable
89
- when Array
90
- enumerable.each_with_index do |object, index|
91
- make_params("#{key}[#{index}]", object, memo)
92
- end
93
- when Hash
94
- enumerable.each do |hash_key, object|
95
- make_params("#{key}[#{hash_key}]", object, memo)
96
- end
97
- else
98
- memo[key] = enumerable
93
+ when Array
94
+ enumerable.each_with_index do |object, index|
95
+ make_params("#{key}[#{index}]", object, memo)
96
+ end
97
+ when Hash
98
+ enumerable.each do |hash_key, object|
99
+ make_params("#{key}[#{hash_key}]", object, memo)
100
+ end
101
+ else
102
+ memo[key] = enumerable
99
103
  end
100
104
  memo
101
105
  end
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bcrypt'
2
4
 
3
5
  module Sequent
4
6
  module Core
5
7
  module Helpers
6
-
7
8
  #
8
9
  # You can use this in Commands to handle for instance passwords
9
10
  # safely. It uses BCrypt to encrypt the Secret.
@@ -55,7 +56,6 @@ module Sequent
55
56
  # See +re_encrypt_secret+
56
57
  # See +verify_secret+
57
58
  class Secret
58
-
59
59
  class << self
60
60
  def deserialize_from_json(value)
61
61
  new(value)
@@ -65,7 +65,8 @@ module Sequent
65
65
  # Creates a hash for the given clear text password.
66
66
  #
67
67
  def encrypt_secret(clear_text_secret)
68
- fail ArgumentError.new('clear_text_secret can not be blank') if clear_text_secret.blank?
68
+ fail ArgumentError, 'clear_text_secret can not be blank' if clear_text_secret.blank?
69
+
69
70
  BCrypt::Password.create(clear_text_secret)
70
71
  end
71
72
 
@@ -74,8 +75,8 @@ module Sequent
74
75
  # (essentially re-creating the secret hash).
75
76
  #
76
77
  def re_encrypt_secret(clear_text_secret, hashed_secret)
77
- fail ArgumentError.new('clear_text_secret can not be blank') if clear_text_secret.blank?
78
- fail ArgumentError.new('hashed_secret can not be blank') if hashed_secret.blank?
78
+ fail ArgumentError, 'clear_text_secret can not be blank' if clear_text_secret.blank?
79
+ fail ArgumentError, 'hashed_secret can not be blank' if hashed_secret.blank?
79
80
 
80
81
  BCrypt::Engine.hash_secret(clear_text_secret, hashed_secret)
81
82
  end
@@ -84,7 +85,7 @@ module Sequent
84
85
  # Verifies that the hashed and clear text secret are equal.
85
86
  #
86
87
  def verify_secret(hashed_secret, clear_text_secret)
87
- return false if (hashed_secret.blank? || clear_text_secret.blank?)
88
+ return false if hashed_secret.blank? || clear_text_secret.blank?
88
89
 
89
90
  BCrypt::Password.new(hashed_secret) == clear_text_secret
90
91
  end
@@ -93,12 +94,13 @@ module Sequent
93
94
  attr_reader :value
94
95
 
95
96
  def initialize(value)
96
- fail ArgumentError.new('value can not be blank') if value.blank?
97
- if value.is_a?(Secret)
98
- @value = value.value
99
- else
100
- @value = value
101
- end
97
+ fail ArgumentError, 'value can not be blank' if value.blank?
98
+
99
+ @value = if value.is_a?(Secret)
100
+ value.value
101
+ else
102
+ value
103
+ end
102
104
  end
103
105
 
104
106
  def encrypt
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  module Helpers
@@ -9,14 +11,13 @@ module Sequent
9
11
  module StringSupport
10
12
  def to_s
11
13
  s = "#{self.class.name}: "
12
- self.instance_variables.each do |name|
13
- value = self.instance_variable_get("#{name}")
14
+ instance_variables.each do |name|
15
+ value = instance_variable_get(name.to_s)
14
16
  s += "#{name}=[#{value}], "
15
17
  end
16
- "{" + s.chomp(", ") + "}"
18
+ '{' + s.chomp(', ') + '}'
17
19
  end
18
20
  end
19
-
20
21
  end
21
22
  end
22
23
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../ext/ext'
2
4
  require_relative 'array_with_type'
3
5
 
@@ -16,10 +18,11 @@ module Sequent
16
18
  ::DateTime => ->(value) { parse_to_date_time(value) },
17
19
  ::Sequent::Core::Helpers::ArrayWithType => ->(values, type_in_array) { parse_array(values, type_in_array) },
18
20
  ::Sequent::Core::Helpers::Secret => ->(value) { Sequent::Core::Helpers::Secret.new(value).encrypt },
19
- }
21
+ }.freeze
20
22
 
21
23
  def self.parse_to_integer(value)
22
24
  return value if value.is_a?(Integer)
25
+
23
26
  Integer(value, 10) unless value.blank?
24
27
  end
25
28
 
@@ -35,12 +38,13 @@ module Sequent
35
38
  if value.blank? && !(value.is_a?(TrueClass) || value.is_a?(FalseClass))
36
39
  nil
37
40
  else
38
- (value.is_a?(TrueClass) || value == "true")
41
+ (value.is_a?(TrueClass) || value == 'true')
39
42
  end
40
43
  end
41
44
 
42
45
  def self.parse_to_date(value)
43
46
  return if value.blank?
47
+
44
48
  value.is_a?(Date) ? value : Date.iso8601(value.dup)
45
49
  end
46
50
 
@@ -50,6 +54,7 @@ module Sequent
50
54
 
51
55
  def self.parse_array(values, type_in_array)
52
56
  fail "invalid value for array(): \"#{values}\"" unless values.is_a?(Array)
57
+
53
58
  values.map do |item|
54
59
  if item.respond_to?(:parse_attrs_to_correct_types)
55
60
  item.parse_attrs_to_correct_types
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
  require_relative 'value_validators'
3
5
 
@@ -16,7 +18,10 @@ module Sequent
16
18
  #
17
19
  class StringValidator < ActiveModel::EachValidator
18
20
  def validate_each(subject, attribute, value)
19
- subject.errors.add attribute, :invalid_string unless Sequent::Core::Helpers::ValueValidators.for(String).valid_value?(value)
21
+ unless Sequent::Core::Helpers::ValueValidators.for(String).valid_value?(value)
22
+ subject.errors.add attribute,
23
+ :invalid_string
24
+ end
20
25
  end
21
26
  end
22
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_model'
2
4
 
3
5
  module Sequent
@@ -5,7 +7,6 @@ module Sequent
5
7
  TypeConversionError = Class.new(RuntimeError)
6
8
 
7
9
  module Helpers
8
-
9
10
  # Will parse all values to the correct types.
10
11
  # The raw values are typically posted from the web and are therefor mostly strings.
11
12
  # To parse a raw value your class must have a parse_from_string method that returns the parsed values.
@@ -14,8 +15,9 @@ module Sequent
14
15
  def parse_attrs_to_correct_types
15
16
  the_copy = dup
16
17
  the_copy.class.types.each do |name, type|
17
- raw_value = the_copy.send("#{name}")
18
+ raw_value = the_copy.send(name.to_s)
18
19
  next if raw_value.nil?
20
+
19
21
  if raw_value.respond_to?(:parse_attrs_to_correct_types)
20
22
  the_copy.send("#{name}=", raw_value.parse_attrs_to_correct_types)
21
23
  else
@@ -24,7 +26,7 @@ module Sequent
24
26
  end
25
27
  end
26
28
  the_copy
27
- rescue => e
29
+ rescue StandardError => e
28
30
  raise TypeConversionError, e.message
29
31
  end
30
32
  end
@@ -1,12 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'securerandom'
2
4
 
3
5
  module Sequent
4
6
  module Core
5
7
  module Helpers
6
8
  module UuidHelper
7
-
8
9
  def new_uuid
9
- warn "DEPRECATION WARNING: Sequent::Core::Helpers::UuidHelper.new_uuid is deprecated. Use Sequent.new_uuid instead"
10
+ warn <<~EOS
11
+ DEPRECATION WARNING: Sequent::Core::Helpers::UuidHelper.new_uuid is deprecated. Use Sequent.new_uuid instead
12
+ EOS
10
13
  Sequent.new_uuid
11
14
  end
12
15
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../ext/ext'
2
4
 
3
5
  module Sequent
@@ -6,7 +8,7 @@ module Sequent
6
8
  class ValueValidators
7
9
  INVALID_STRING_CHARS = [
8
10
  "\u0000",
9
- ]
11
+ ].freeze
10
12
 
11
13
  VALIDATORS = {
12
14
  ::Symbol => ->(_) { true },
@@ -14,36 +16,48 @@ module Sequent
14
16
  ::Integer => ->(value) { valid_integer?(value) },
15
17
  ::Boolean => ->(value) { valid_bool?(value) },
16
18
  ::Date => ->(value) { valid_date?(value) },
17
- ::DateTime => ->(value) { valid_date_time?(value) }
18
- }
19
+ ::DateTime => ->(value) { valid_date_time?(value) },
20
+ }.freeze
19
21
 
20
22
  def self.valid_integer?(value)
21
23
  value.blank? || Integer(value)
22
- rescue
24
+ rescue StandardError
23
25
  false
24
26
  end
25
27
 
26
28
  def self.valid_bool?(value)
27
29
  return true if value.blank?
28
- value.is_a?(TrueClass) || value.is_a?(FalseClass) || value == "true" || value == "false"
30
+
31
+ value.is_a?(TrueClass) || value.is_a?(FalseClass) || value == 'true' || value == 'false'
29
32
  end
30
33
 
31
34
  def self.valid_date?(value)
32
35
  return true if value.blank?
33
36
  return true if value.is_a?(Date)
34
37
  return false unless value =~ /\d{4}-\d{2}-\d{2}/
35
- !!Date.iso8601(value) rescue false
38
+
39
+ begin
40
+ !!Date.iso8601(value)
41
+ rescue StandardError
42
+ false
43
+ end
36
44
  end
37
45
 
38
46
  def self.valid_date_time?(value)
39
47
  return true if value.blank?
40
- value.is_a?(DateTime) || !!DateTime.iso8601(value.dup) rescue false
48
+
49
+ begin
50
+ value.is_a?(DateTime) || !!DateTime.iso8601(value.dup)
51
+ rescue StandardError
52
+ false
53
+ end
41
54
  end
42
55
 
43
56
  def self.valid_string?(value)
44
57
  return true if value.nil?
45
- value.to_s && !INVALID_STRING_CHARS.any? { |invalid_char| value.to_s.include?(invalid_char) }
46
- rescue
58
+
59
+ value.to_s && INVALID_STRING_CHARS.none? { |invalid_char| value.to_s.include?(invalid_char) }
60
+ rescue StandardError
47
61
  false
48
62
  end
49
63
 
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record'
2
4
  require_relative './persistor'
3
5
 
4
6
  module Sequent
5
7
  module Core
6
8
  module Persistors
7
-
8
9
  #
9
10
  # The ActiveRecordPersistor uses ActiveRecord to update the projection
10
11
  #
@@ -17,14 +18,21 @@ module Sequent
17
18
  class ActiveRecordPersistor
18
19
  include Persistor
19
20
 
20
- def update_record(record_class, event, where_clause = {aggregate_id: event.aggregate_id}, options = {}, &block)
21
+ def update_record(record_class, event, where_clause = {aggregate_id: event.aggregate_id}, options = {})
21
22
  record = record_class.unscoped.where(where_clause).first
22
- raise("Record of class #{record_class} with where clause #{where_clause} not found while handling event #{event}") unless record
23
+ unless record
24
+ fail(<<~EOS)
25
+ Record of class #{record_class} with where clause #{where_clause} not found while handling event #{event}
26
+ EOS
27
+ end
28
+
23
29
  record.updated_at = event.created_at if record.respond_to?(:updated_at)
24
30
  yield record if block_given?
25
- update_sequence_number = options.key?(:update_sequence_number) ?
26
- options[:update_sequence_number] :
31
+ update_sequence_number = if options.key?(:update_sequence_number)
32
+ options[:update_sequence_number]
33
+ else
27
34
  record.respond_to?(:sequence_number=)
35
+ end
28
36
  record.sequence_number = event.sequence_number if update_sequence_number
29
37
  record.save!
30
38
  end
@@ -42,11 +50,13 @@ module Sequent
42
50
  query = array_of_value_hashes.map do |values|
43
51
  insert_manager = new_insert_manager
44
52
  insert_manager.into(table)
45
- insert_manager.insert(values.map do |key, value|
46
- convert_to_values(key, table, value)
47
- end)
53
+ insert_manager.insert(
54
+ values.map do |key, value|
55
+ convert_to_values(key, table, value)
56
+ end,
57
+ )
48
58
  insert_manager.to_sql
49
- end.join(";")
59
+ end.join(';')
50
60
 
51
61
  execute_sql(query)
52
62
  end