sequent 4.0.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
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