sequent 3.3.1 → 4.1.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 +31 -25
  3. data/lib/notices.rb +6 -0
  4. data/lib/sequent/application_record.rb +2 -0
  5. data/lib/sequent/configuration.rb +29 -29
  6. data/lib/sequent/core/aggregate_repository.rb +24 -14
  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 +30 -11
  12. data/lib/sequent/core/command_record.rb +12 -4
  13. data/lib/sequent/core/command_service.rb +41 -25
  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 +20 -15
  18. data/lib/sequent/core/event_record.rb +7 -7
  19. data/lib/sequent/core/event_store.rb +75 -49
  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 +64 -33
  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 -4
  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 +7 -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 +6 -0
  59. data/lib/sequent/generator/project.rb +3 -1
  60. data/lib/sequent/generator/template_project/Gemfile +1 -1
  61. data/lib/sequent/generator/template_project/spec/app/projectors/post_projector_spec.rb +1 -1
  62. data/lib/sequent/generator/template_project/spec/lib/post/post_command_handler_spec.rb +1 -1
  63. data/lib/sequent/generator.rb +3 -4
  64. data/lib/sequent/migrations/executor.rb +30 -9
  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 +93 -44
  72. data/lib/sequent/rake/migration_tasks.rb +59 -23
  73. data/lib/sequent/rake/tasks.rb +5 -2
  74. data/lib/sequent/sequent.rb +6 -1
  75. data/lib/sequent/support/database.rb +39 -17
  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 +39 -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 +194 -0
  85. data/lib/sequent/util/printer.rb +6 -5
  86. data/lib/sequent/util/skip_if_already_processing.rb +21 -5
  87. data/lib/sequent/util/timer.rb +2 -0
  88. data/lib/sequent/util/util.rb +3 -0
  89. data/lib/sequent.rb +4 -0
  90. data/lib/version.rb +3 -1
  91. metadata +110 -59
@@ -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'
@@ -9,33 +11,44 @@ require_relative 'association_validator'
9
11
  module Sequent
10
12
  module Core
11
13
  module Helpers
12
- # Provides functionality for defining attributes with their types
14
+ # Provides functionality for defining attributes with their types.
13
15
  #
14
- # Since our Commands and ValueObjects are not backed by a database like e.g. rails
16
+ # Since our Commands and ValueObjects are not backed by a database like e.g. Rails
15
17
  # we can not infer their types. We need the types to be able to parse from and to json.
16
- # We could have stored te type information in the json, but we didn't.
17
- #
18
18
  # You typically do not need to include this module in your classes. If you extend from
19
- # Sequent::Core::ValueObject, Sequent::Core::Event or Sequent::Core::BaseCommand you will
19
+ # Sequent::ValueObject, Sequent::Event or Sequent::Command you will
20
20
  # get this functionality for free.
21
21
  #
22
+ # Example:
23
+ #
24
+ # attrs name: String, age: Integer, born: Date
25
+ #
26
+ # Currently Sequent supports the following types:
27
+ #
28
+ # - String
29
+ # - Integer
30
+ # - Boolean
31
+ # - Date
32
+ # - DateTime
33
+ # - Subclasses of Sequent::ValueObject
34
+ # - Lists defined as `array(String)`
35
+ # - BigDecimal
36
+ # - Sequent::Secret
37
+ #
22
38
  module AttributeSupport
23
39
  class UnknownAttributeError < StandardError; end
24
40
 
25
41
  # module containing class methods to be added
26
42
  module ClassMethods
27
-
28
43
  def types
29
44
  @types ||= {}
30
- if @merged_types
31
- @merged_types
32
- else
33
- @merged_types = is_a?(Class) && superclass.respond_to?(:types) ? @types.merge(superclass.types) : @types
34
- included_modules.select { |m| m.include? Sequent::Core::Helpers::AttributeSupport }.each do |mod|
35
- @merged_types.merge!(mod.types)
36
- end
37
- @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)
38
50
  end
51
+ @merged_types
39
52
  end
40
53
 
41
54
  def attrs(args)
@@ -44,14 +57,15 @@ module Sequent
44
57
  associations = []
45
58
  args.each do |attribute, type|
46
59
  attr_accessor attribute
60
+
47
61
  if included_modules.include?(Sequent::Core::Helpers::TypeConversionSupport)
48
62
  Sequent::Core::Helpers::DefaultValidators.for(type).add_validations_for(self, attribute)
49
63
  end
50
64
 
51
- if type.class == Sequent::Core::Helpers::ArrayWithType
65
+ if type.instance_of?(Sequent::Core::Helpers::ArrayWithType)
52
66
  associations << attribute
53
67
  elsif included_modules.include?(ActiveModel::Validations) &&
54
- type.included_modules.include?(Sequent::Core::Helpers::AttributeSupport)
68
+ type.included_modules.include?(Sequent::Core::Helpers::AttributeSupport)
55
69
  associations << attribute
56
70
  end
57
71
  end
@@ -63,9 +77,9 @@ module Sequent
63
77
  def update_all_attributes(attrs)
64
78
  super if defined?(super)
65
79
  ensure_known_attributes(attrs)
66
- #{@types.map { |attribute, _|
67
- "@#{attribute} = attrs[:#{attribute}]"
68
- }.join("\n ")}
80
+ #{@types.map do |attribute, _|
81
+ "@#{attribute} = attrs[:#{attribute}]"
82
+ end.join("\n ")}
69
83
  self
70
84
  end
71
85
  EOS
@@ -73,9 +87,9 @@ EOS
73
87
  class_eval <<EOS
74
88
  def update_all_attributes_from_json(attrs)
75
89
  super if defined?(super)
76
- #{@types.map { |attribute, type|
77
- "@#{attribute} = #{type}.deserialize_from_json(attrs['#{attribute}'])"
78
- }.join("\n ")}
90
+ #{@types.map do |attribute, type|
91
+ "@#{attribute} = #{type}.deserialize_from_json(attrs['#{attribute}'])"
92
+ end.join("\n ")}
79
93
  end
80
94
  EOS
81
95
  end
@@ -92,17 +106,33 @@ EOS
92
106
 
93
107
  def deserialize_from_json(args)
94
108
  unless args.nil?
95
- obj = allocate()
109
+ obj = allocate
110
+
111
+ upcast!(args)
112
+
96
113
  obj.update_all_attributes_from_json(args)
97
114
  obj
98
115
  end
99
116
  end
100
117
 
101
-
102
118
  def numeric?(object)
103
- true if Float(object) rescue false
119
+ true if Float(object)
120
+ rescue StandardError
121
+ false
122
+ end
123
+
124
+ def upcast(&block)
125
+ @upcasters ||= []
126
+ @upcasters.push(block)
104
127
  end
105
128
 
129
+ def upcast!(hash)
130
+ return if @upcasters.nil?
131
+
132
+ @upcasters.each do |upcaster|
133
+ upcaster.call(hash)
134
+ end
135
+ end
106
136
  end
107
137
 
108
138
  # extend host class with class methods when we're included
@@ -110,11 +140,10 @@ EOS
110
140
  host_class.extend(ClassMethods)
111
141
  end
112
142
 
113
-
114
143
  def attributes
115
144
  hash = HashWithIndifferentAccess.new
116
145
  self.class.types.each do |name, _|
117
- value = self.instance_variable_get("@#{name}")
146
+ value = instance_variable_get("@#{name}")
118
147
  hash[name] = if value.respond_to?(:attributes)
119
148
  value.attributes
120
149
  else
@@ -127,7 +156,7 @@ EOS
127
156
  def as_json(opts = {})
128
157
  hash = HashWithIndifferentAccess.new
129
158
  self.class.types.each do |name, _|
130
- value = self.instance_variable_get("@#{name}")
159
+ value = instance_variable_get("@#{name}")
131
160
  hash[name] = if value.respond_to?(:as_json)
132
161
  value.as_json(opts)
133
162
  else
@@ -144,15 +173,15 @@ EOS
144
173
  def validation_errors(prefix = nil)
145
174
  result = errors.to_hash
146
175
  self.class.types.each do |field|
147
- value = self.instance_variable_get("@#{field[0]}")
176
+ value = instance_variable_get("@#{field[0]}")
148
177
  if value.respond_to? :validation_errors
149
- value.validation_errors.each { |k, v| result["#{field[0].to_s}_#{k.to_s}".to_sym] = v }
150
- 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?
151
180
  value
152
181
  .select { |val| val.respond_to?(:validation_errors) }
153
182
  .each_with_index do |val, index|
154
183
  val.validation_errors.each do |k, v|
155
- result["#{field[0].to_s}_#{index}_#{k.to_s}".to_sym] = v
184
+ result["#{field[0]}_#{index}_#{k}".to_sym] = v
156
185
  end
157
186
  end
158
187
  end
@@ -164,7 +193,9 @@ EOS
164
193
  return unless Sequent.configuration.strict_check_attributes_on_apply_events
165
194
 
166
195
  unknowns = attrs.keys.map(&:to_s) - self.class.types.keys.map(&:to_s)
167
- 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
168
199
  end
169
200
  end
170
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,16 +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 = {})
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
11
15
  attrs.each do |name, value|
12
- self.send("#{name}=", value)
16
+ send("#{name}=", value)
13
17
  end
14
18
  self
15
19
  end
16
-
17
20
  end
18
21
  end
19
22
  end
20
23
  end
21
-
@@ -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