sequent 4.0.0 → 4.1.0

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.
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