sequent 4.0.0 → 4.3.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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequent +33 -26
  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 +48 -13
  7. data/lib/sequent/core/aggregate_root.rb +36 -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 +89 -51
  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 +53 -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 +30 -9
  51. data/lib/sequent/core/transactions/no_transactions.rb +2 -1
  52. data/lib/sequent/core/transactions/read_only_active_record_transaction_provider.rb +46 -0
  53. data/lib/sequent/core/transactions/transactions.rb +3 -0
  54. data/lib/sequent/core/value_object.rb +8 -10
  55. data/lib/sequent/core/workflow.rb +35 -5
  56. data/lib/sequent/generator/aggregate.rb +16 -10
  57. data/lib/sequent/generator/command.rb +26 -19
  58. data/lib/sequent/generator/event.rb +19 -17
  59. data/lib/sequent/generator/generator.rb +2 -0
  60. data/lib/sequent/generator/project.rb +9 -0
  61. data/lib/sequent/generator/template_project/Gemfile +1 -1
  62. data/lib/sequent/generator/template_project/ruby-version +1 -0
  63. data/lib/sequent/generator.rb +2 -0
  64. data/lib/sequent/migrations/executor.rb +22 -13
  65. data/lib/sequent/migrations/functions.rb +5 -6
  66. data/lib/sequent/migrations/migrate_events.rb +12 -9
  67. data/lib/sequent/migrations/migrations.rb +2 -1
  68. data/lib/sequent/migrations/planner.rb +33 -23
  69. data/lib/sequent/migrations/projectors.rb +4 -3
  70. data/lib/sequent/migrations/sql.rb +2 -0
  71. data/lib/sequent/migrations/view_schema.rb +84 -45
  72. data/lib/sequent/rake/migration_tasks.rb +58 -22
  73. data/lib/sequent/rake/tasks.rb +5 -2
  74. data/lib/sequent/sequent.rb +2 -0
  75. data/lib/sequent/support/database.rb +30 -15
  76. data/lib/sequent/support/view_projection.rb +6 -3
  77. data/lib/sequent/support/view_schema.rb +2 -0
  78. data/lib/sequent/support.rb +2 -0
  79. data/lib/sequent/test/command_handler_helpers.rb +35 -17
  80. data/lib/sequent/test/event_handler_helpers.rb +10 -4
  81. data/lib/sequent/test/event_stream_helpers.rb +7 -3
  82. data/lib/sequent/test/time_comparison.rb +12 -5
  83. data/lib/sequent/test.rb +2 -0
  84. data/lib/sequent/util/dry_run.rb +28 -20
  85. data/lib/sequent/util/printer.rb +6 -5
  86. data/lib/sequent/util/skip_if_already_processing.rb +3 -1
  87. data/lib/sequent/util/timer.rb +2 -0
  88. data/lib/sequent/util/util.rb +2 -0
  89. data/lib/sequent.rb +2 -0
  90. data/lib/version.rb +3 -1
  91. metadata +84 -67
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support'
2
4
  require_relative '../ext/ext'
3
5
  require_relative 'array_with_type'
@@ -38,18 +40,15 @@ module Sequent
38
40
 
39
41
  # module containing class methods to be added
40
42
  module ClassMethods
41
-
42
43
  def types
43
44
  @types ||= {}
44
- if @merged_types
45
- @merged_types
46
- else
47
- @merged_types = is_a?(Class) && superclass.respond_to?(:types) ? @types.merge(superclass.types) : @types
48
- included_modules.select { |m| m.include? Sequent::Core::Helpers::AttributeSupport }.each do |mod|
49
- @merged_types.merge!(mod.types)
50
- end
51
- @merged_types
45
+ return @merged_types if @merged_types
46
+
47
+ @merged_types = is_a?(Class) && superclass.respond_to?(:types) ? @types.merge(superclass.types) : @types
48
+ included_modules.select { |m| m.include? Sequent::Core::Helpers::AttributeSupport }.each do |mod|
49
+ @merged_types.merge!(mod.types)
52
50
  end
51
+ @merged_types
53
52
  end
54
53
 
55
54
  def attrs(args)
@@ -58,14 +57,15 @@ module Sequent
58
57
  associations = []
59
58
  args.each do |attribute, type|
60
59
  attr_accessor attribute
60
+
61
61
  if included_modules.include?(Sequent::Core::Helpers::TypeConversionSupport)
62
62
  Sequent::Core::Helpers::DefaultValidators.for(type).add_validations_for(self, attribute)
63
63
  end
64
64
 
65
- if type.class == Sequent::Core::Helpers::ArrayWithType
65
+ if type.instance_of?(Sequent::Core::Helpers::ArrayWithType)
66
66
  associations << attribute
67
67
  elsif included_modules.include?(ActiveModel::Validations) &&
68
- type.included_modules.include?(Sequent::Core::Helpers::AttributeSupport)
68
+ type.included_modules.include?(Sequent::Core::Helpers::AttributeSupport)
69
69
  associations << attribute
70
70
  end
71
71
  end
@@ -77,9 +77,9 @@ module Sequent
77
77
  def update_all_attributes(attrs)
78
78
  super if defined?(super)
79
79
  ensure_known_attributes(attrs)
80
- #{@types.map { |attribute, _|
81
- "@#{attribute} = attrs[:#{attribute}]"
82
- }.join("\n ")}
80
+ #{@types.map do |attribute, _|
81
+ "@#{attribute} = attrs[:#{attribute}]"
82
+ end.join("\n ")}
83
83
  self
84
84
  end
85
85
  EOS
@@ -87,9 +87,9 @@ EOS
87
87
  class_eval <<EOS
88
88
  def update_all_attributes_from_json(attrs)
89
89
  super if defined?(super)
90
- #{@types.map { |attribute, type|
91
- "@#{attribute} = #{type}.deserialize_from_json(attrs['#{attribute}'])"
92
- }.join("\n ")}
90
+ #{@types.map do |attribute, type|
91
+ "@#{attribute} = #{type}.deserialize_from_json(attrs['#{attribute}'])"
92
+ end.join("\n ")}
93
93
  end
94
94
  EOS
95
95
  end
@@ -106,17 +106,33 @@ EOS
106
106
 
107
107
  def deserialize_from_json(args)
108
108
  unless args.nil?
109
- obj = allocate()
109
+ obj = allocate
110
+
111
+ upcast!(args)
112
+
110
113
  obj.update_all_attributes_from_json(args)
111
114
  obj
112
115
  end
113
116
  end
114
117
 
115
-
116
118
  def numeric?(object)
117
- true if Float(object) rescue false
119
+ true if Float(object)
120
+ rescue StandardError
121
+ false
118
122
  end
119
123
 
124
+ def upcast(&block)
125
+ @upcasters ||= []
126
+ @upcasters.push(block)
127
+ end
128
+
129
+ def upcast!(hash)
130
+ return if @upcasters.nil?
131
+
132
+ @upcasters.each do |upcaster|
133
+ upcaster.call(hash)
134
+ end
135
+ end
120
136
  end
121
137
 
122
138
  # extend host class with class methods when we're included
@@ -124,11 +140,10 @@ EOS
124
140
  host_class.extend(ClassMethods)
125
141
  end
126
142
 
127
-
128
143
  def attributes
129
144
  hash = HashWithIndifferentAccess.new
130
145
  self.class.types.each do |name, _|
131
- value = self.instance_variable_get("@#{name}")
146
+ value = instance_variable_get("@#{name}")
132
147
  hash[name] = if value.respond_to?(:attributes)
133
148
  value.attributes
134
149
  else
@@ -141,7 +156,7 @@ EOS
141
156
  def as_json(opts = {})
142
157
  hash = HashWithIndifferentAccess.new
143
158
  self.class.types.each do |name, _|
144
- value = self.instance_variable_get("@#{name}")
159
+ value = instance_variable_get("@#{name}")
145
160
  hash[name] = if value.respond_to?(:as_json)
146
161
  value.as_json(opts)
147
162
  else
@@ -158,15 +173,15 @@ EOS
158
173
  def validation_errors(prefix = nil)
159
174
  result = errors.to_hash
160
175
  self.class.types.each do |field|
161
- value = self.instance_variable_get("@#{field[0]}")
176
+ value = instance_variable_get("@#{field[0]}")
162
177
  if value.respond_to? :validation_errors
163
- value.validation_errors.each { |k, v| result["#{field[0].to_s}_#{k.to_s}".to_sym] = v }
164
- elsif field[1].class == ArrayWithType and value.present?
178
+ value.validation_errors.each { |k, v| result["#{field[0]}_#{k}".to_sym] = v }
179
+ elsif field[1].instance_of?(ArrayWithType) && value.present?
165
180
  value
166
181
  .select { |val| val.respond_to?(:validation_errors) }
167
182
  .each_with_index do |val, index|
168
183
  val.validation_errors.each do |k, v|
169
- result["#{field[0].to_s}_#{index}_#{k.to_s}".to_sym] = v
184
+ result["#{field[0]}_#{index}_#{k}".to_sym] = v
170
185
  end
171
186
  end
172
187
  end
@@ -178,7 +193,9 @@ EOS
178
193
  return unless Sequent.configuration.strict_check_attributes_on_apply_events
179
194
 
180
195
  unknowns = attrs.keys.map(&:to_s) - self.class.types.keys.map(&:to_s)
181
- raise UnknownAttributeError.new("#{self.class.name} does not specify attrs: #{unknowns.join(", ")}") if unknowns.any?
196
+ if unknowns.any?
197
+ fail UnknownAttributeError, "#{self.class.name} does not specify attrs: #{unknowns.join(', ')}"
198
+ end
182
199
  end
183
200
  end
184
201
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sequent
2
4
  module Core
3
5
  module Helpers
@@ -24,8 +26,7 @@ module Sequent
24
26
  #
25
27
  module AutosetAttributes
26
28
  module ClassMethods
27
-
28
- @@autoset_ignore_attributes = %w{aggregate_id sequence_number created_at}
29
+ @@autoset_ignore_attributes = %w[aggregate_id sequence_number created_at]
29
30
 
30
31
  def set_autoset_ignore_attributes(attribute_names)
31
32
  @@autoset_ignore_attributes = attribute_names
@@ -39,7 +40,7 @@ module Sequent
39
40
  event_classes.each do |event_class|
40
41
  on event_class do |event|
41
42
  self.class.event_attribute_keys(event_class).each do |attribute_name|
42
- instance_variable_set(:"@#{attribute_name.to_s}", event.send(attribute_name.to_sym))
43
+ instance_variable_set(:"@#{attribute_name}", event.send(attribute_name.to_sym))
43
44
  end
44
45
  end
45
46
  end
@@ -53,4 +54,3 @@ module Sequent
53
54
  end
54
55
  end
55
56
  end
56
-
@@ -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