metaractor 2.1.1 → 3.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 871ec542d6215f116b734516dc46ca8254cfa558576a43bbe58130c32dc043c3
4
- data.tar.gz: 35f548db1260d6702ee931c9fa9c9a2bc89b06d318f040839822827dbbd6c928
3
+ metadata.gz: 67f974131ea1d40f037b6bd29173092b95ab31fbe2263d4274d8dd614ba0483c
4
+ data.tar.gz: 25bfc2e214f0b8da6fe6964a8426989454ea244d841138b341b1a70f4ec2e5b5
5
5
  SHA512:
6
- metadata.gz: ee9e4424b4040ce356cfaa092e83c302e57bcac4716d80e4c89ac59551f48f0c97dfc9fa2e159988ca0188adb79087a7f085f21f972853fafc8541066d92e361
7
- data.tar.gz: 474a153dec5a43774e46b59adeb64306ac8d7b10359ccbe77cec3fd01f1a1919ce9075fccc2b8dbbcd4ee802faf8d81e152c3bec98fc960285887e9beaa7a7b7
6
+ metadata.gz: d0fbacb1db9083b9c596f35d9e8eaaabe54fef7c8ede4ac3ad2f92b0b086efec4c55ced03caa0211325344a3242006d6aea0e0b72e96d16aada1b929168f2e7d
7
+ data.tar.gz: 307a426d305331d9730b6b12eba50ff0703706e53b7b8235e9082e7d5ddf910644263662465462f838c5c79b0c439858dd03daa19afd74e813bd2bc3c05b6d03
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
  gem 'pry-byebug'
5
+ gem 'awesome_print'
data/README.md CHANGED
@@ -44,7 +44,7 @@ result.failure?
44
44
  # => true
45
45
  result.valid?
46
46
  # => false
47
- result.errors
47
+ result.error_messages
48
48
  # => ["Required parameters: (user_id or user)"]
49
49
  ```
50
50
 
@@ -68,20 +68,41 @@ Metaractor supports complex required parameter statements and you can chain thes
68
68
  required and: [:token, or: [:recipient_id, :recipient] ]
69
69
  ```
70
70
 
71
+ You can also mark a parameter as required with the `required` option:
72
+ ```ruby
73
+ parameter :user, required: true
74
+ ```
75
+
71
76
  ### Optional Parameters
72
77
  As optional parameters have no enforcement, they are merely advisory.
73
78
  ```ruby
74
79
  optional :enable_logging
75
80
  ```
76
81
 
77
- ### Skipping Blank Parameter Removal
82
+ ### Parameter Options
83
+ Metaractor supports arbitrary parameter options. The following are currently built in.
84
+ Note that you can specify a block of `required` or `optional` parameters and then use
85
+ `parameter` or `parameters` to add options to one or more of them.
86
+
87
+ #### Skipping Blank Parameter Removal
78
88
  By default Metaractor removes blank values that are passed in. You may skip this behavior on a per-parameter basis:
79
89
  ```ruby
80
- allow_blank :name
90
+ parameter :name, allow_blank: true
81
91
  ```
82
92
 
83
93
  You may check to see if a parameter exists via `context.has_key?`.
84
94
 
95
+ #### Default Values
96
+ You can specify a default value for a parameter:
97
+ ```ruby
98
+ optional :role, default: :user
99
+ ```
100
+
101
+ This works with `allow_blank` and can also be anything that responds to `#call`.
102
+ ```ruby
103
+ parameter :role, allow_blank: true, default: -> { context.default_role }
104
+ ```
105
+
85
106
  ### Custom Validation
86
107
  Metaractor supports doing custom validation before any user supplied before_hooks run.
87
108
  ```ruby
@@ -161,6 +182,64 @@ result.errors.to_h
161
182
  # }
162
183
  ```
163
184
 
185
+ ### I18n
186
+ As of v3.0.0, metaractor supports i18n along with structured errors.
187
+ ```ruby
188
+ module Users
189
+ class UpdateUser
190
+ include Metaractor
191
+
192
+ optional :is_admin
193
+ optional :user
194
+
195
+ def call
196
+ fail_with_error!(
197
+ errors: {
198
+ base: :invalid_configuration,
199
+ is_admin: :true_or_false,
200
+ user: [ title: :blank, username: [:unique, :blank] ]
201
+ }
202
+ )
203
+ end
204
+ end
205
+ end
206
+ ```
207
+
208
+ Locale:
209
+ ```yaml
210
+ en:
211
+ errors:
212
+ parameters:
213
+ invalid_configuration: 'Invalid configuration'
214
+ blank: '%{parameter} cannot be blank'
215
+ unique: '%{parameter} must be unique'
216
+
217
+ users:
218
+ is_admin:
219
+ true_or_false: 'must be true or false'
220
+ user:
221
+ username:
222
+ unique: 'Username has already been taken'
223
+ ```
224
+
225
+ Metaractor will attempt to use the namespace of the code that reported the error.
226
+ You can see that above with the `users` key in the locale.
227
+
228
+ The i18n integration will walk its way from the most specific message to the least specific one, stopping at the first one it can find.
229
+ We currently expose the following variables for use in the message:
230
+ - `error_key`: the error we added (ex: `blank` or `invalid_configuration`)
231
+ - `parameter`: the name of the parameter
232
+
233
+ You can also use this feature to work with machine readable keys:
234
+ ```ruby
235
+ result = Users::UpdateUser.call
236
+ if result.failure? &&
237
+ result.errors[:is_admin] == :true_or_false
238
+
239
+ # handle this specific case
240
+ end
241
+ ```
242
+
164
243
  ### Spec Helpers
165
244
  Enable the helpers and/or matchers:
166
245
  ```ruby
@@ -221,8 +300,8 @@ expect(result).to include_errors(
221
300
  expect(result).to include_errors('user.title cannot be blank')
222
301
  ```
223
302
 
224
- ### Error Output
225
- Metaractor customizes the exception message for `Interactor::Failure`:
303
+ ### Hash Formatting
304
+ Metaractor customizes the output for `Metaractor::Errors#inspect` and `Interactor::Failure`:
226
305
  ```
227
306
  Interactor::Failure:
228
307
  Errors:
@@ -235,10 +314,12 @@ Interactor::Failure:
235
314
  {:parent=>true, :chained=>true}
236
315
  ```
237
316
 
238
- You can further customize the exception message:
317
+ You can further customize the hash formatting:
239
318
  ```ruby
240
- # Configure FailureOutput to use awesome_print
241
- Metaractor::FailureOutput.hash_formatter = ->(hash) { hash.ai }
319
+ Metaractor.configure do |config|
320
+ # Configure Metaractor to use awesome_print
321
+ config.hash_formatter = ->(hash) { hash.ai }
322
+ end
242
323
  ```
243
324
 
244
325
  ### Further Reading
@@ -8,29 +8,29 @@ module Metaractor
8
8
  super
9
9
  end
10
10
 
11
- def fail_with_error!(message: nil, errors: nil)
12
- add_error(message: message, errors: errors)
11
+ def fail_with_error!(message: nil, errors: nil, **args)
12
+ add_error(message: message, errors: errors, **args)
13
13
  fail!
14
14
  end
15
15
 
16
- def fail_with_errors!(messages: [], errors: {})
17
- add_errors(messages: messages, errors: errors)
16
+ def fail_with_errors!(messages: [], errors: {}, **args)
17
+ add_errors(messages: messages, errors: errors, **args)
18
18
  fail!
19
19
  end
20
20
 
21
- def add_error(message: nil, errors: nil)
21
+ def add_error(message: nil, errors: nil, **args)
22
22
  if message.nil?
23
- add_errors(errors: errors)
23
+ add_errors(errors: errors, **args)
24
24
  else
25
- add_errors(messages: Array(message))
25
+ add_errors(messages: Array(message), **args)
26
26
  end
27
27
  end
28
28
 
29
- def add_errors(messages: [], errors: {})
29
+ def add_errors(messages: [], errors: {}, **args)
30
30
  if !messages.empty?
31
- self.errors.add(errors: { base: messages })
31
+ self.errors.add(errors: { base: messages }, **args)
32
32
  else
33
- self.errors.add(errors: errors)
33
+ self.errors.add(errors: errors, **args)
34
34
  end
35
35
  end
36
36
 
@@ -4,13 +4,72 @@ module Metaractor
4
4
  class Errors
5
5
  extend Forwardable
6
6
 
7
+ class Error
8
+ attr_reader :value, :object
9
+
10
+ def initialize(value:, object: nil)
11
+ @value = value
12
+ @object = object
13
+ end
14
+
15
+ def generate_message(path_elements:)
16
+ if @value.is_a? Symbol
17
+ defaults = []
18
+
19
+ if object.class.respond_to?(:i18n_parent_names) &&
20
+ !object.class.i18n_parent_names.empty?
21
+
22
+ names = object.class.i18n_parent_names
23
+ until names.empty?
24
+ defaults << ['errors', names.join('.'), 'parameters', path_elements.join('.'), @value.to_s].reject do |item|
25
+ item.nil? || item == ''
26
+ end.join('.').to_sym
27
+ names.pop
28
+ end
29
+ end
30
+
31
+ unless path_elements.empty?
32
+ defaults << :"errors.parameters.#{path_elements.join('.')}.#{@value}"
33
+ end
34
+ defaults << :"errors.parameters.#{@value}"
35
+
36
+ key = defaults.shift
37
+ I18n.translate(
38
+ key,
39
+ default: defaults,
40
+ error_key: @value,
41
+ parameter: path_elements.last
42
+ )
43
+ else
44
+ "#{path_elements.join('.')} #{@value}".lstrip
45
+ end
46
+ end
47
+
48
+ def ==(other)
49
+ if other.is_a?(self.class)
50
+ @value == other.value
51
+ else
52
+ @value == other
53
+ end
54
+ end
55
+ alias eql? ==
56
+
57
+ def hash
58
+ @value.hash
59
+ end
60
+
61
+ def inspect
62
+ "(Error) #{@value.inspect}"
63
+ end
64
+ end
65
+
7
66
  def initialize
8
67
  @tree = Sycamore::Tree.new
9
68
  end
10
69
 
11
- def_delegators :@tree, :to_h, :empty?
70
+ def_delegators :@tree, :empty?
12
71
 
13
- def add(error: {}, errors: {})
72
+ def add(error: {}, errors: {}, object: nil)
14
73
  trees = []
15
74
  [error, errors].each do |h|
16
75
  tree = nil
@@ -29,7 +88,17 @@ module Metaractor
29
88
  end
30
89
 
31
90
  trees.each do |tree|
32
- @tree.add(tree)
91
+ tree.each_path do |path|
92
+ node = path.node
93
+ unless node.is_a?(Error)
94
+ node = Error.new(
95
+ value: path.node,
96
+ object: object
97
+ )
98
+ end
99
+
100
+ @tree[path.parent] << node
101
+ end
33
102
  end
34
103
  @tree.compact
35
104
  end
@@ -58,9 +127,9 @@ module Metaractor
58
127
  result = @tree.dig(*path)
59
128
 
60
129
  if result.strict_leaves?
61
- result.nodes
130
+ unwrapped_enum(result.nodes)
62
131
  else
63
- result.to_h
132
+ unwrapped_tree(result).to_h
64
133
  end
65
134
  end
66
135
  alias [] dig
@@ -68,9 +137,15 @@ module Metaractor
68
137
  def include?(*elements)
69
138
  if elements.size == 1 &&
70
139
  elements.first.is_a?(Hash)
71
- @tree.include?(*elements)
140
+ unwrapped_tree.include?(*elements)
72
141
  else
73
- full_messages.include?(*elements)
142
+ if elements.all? {|e| e.is_a? String }
143
+ full_messages.include?(*elements)
144
+ else
145
+ elements.all? do |element|
146
+ @tree.include_path?(element)
147
+ end
148
+ end
74
149
  end
75
150
  end
76
151
 
@@ -83,7 +158,28 @@ module Metaractor
83
158
  end
84
159
  end
85
160
 
86
- new_tree.to_h
161
+ unwrapped_tree(new_tree).to_h
162
+ end
163
+
164
+ def to_h(unwrap: true)
165
+ if unwrap
166
+ unwrapped_tree.to_h
167
+ else
168
+ @tree.to_h
169
+ end
170
+ end
171
+
172
+ def inspect
173
+ str = "<##{self.class.name}: "
174
+
175
+ if !self.empty?
176
+ str << "Errors:\n"
177
+ str << Metaractor.format_hash(to_h(unwrap: false))
178
+ str << "\n"
179
+ end
180
+
181
+ str << ">"
182
+ str
87
183
  end
88
184
 
89
185
  private
@@ -96,7 +192,32 @@ module Metaractor
96
192
  end
97
193
  end
98
194
 
99
- "#{path_elements.join('.')} #{path.node.to_s}".lstrip
195
+ path.node.generate_message(path_elements: path_elements)
100
196
  end
197
+
198
+ def unwrapped_tree(orig_tree = @tree)
199
+ tree = Sycamore::Tree.new
200
+ orig_tree.each_path do |path|
201
+ node = path.node
202
+ if node.is_a? Error
203
+ node = node.value
204
+ end
205
+
206
+ tree[path.parent] << node
207
+ end
208
+
209
+ tree
210
+ end
211
+
212
+ def unwrapped_enum(orig)
213
+ orig.map do |element|
214
+ if element.is_a? Error
215
+ element.value
216
+ else
217
+ element
218
+ end
219
+ end
220
+ end
221
+
101
222
  end
102
223
  end
@@ -1,23 +1,11 @@
1
1
  module Metaractor
2
2
  module FailureOutput
3
- def self.format_hash(hash)
4
- if @hash_formatter.nil?
5
- @hash_formatter = ->(hash){ hash.inspect }
6
- end
7
-
8
- @hash_formatter.call(hash)
9
- end
10
-
11
- def self.hash_formatter=(callable)
12
- @hash_formatter = callable
13
- end
14
-
15
3
  def to_s
16
4
  str = ''
17
5
 
18
6
  if !context.errors.empty?
19
7
  str << "Errors:\n"
20
- str << Metaractor::FailureOutput.format_hash(context.errors.to_h)
8
+ str << Metaractor.format_hash(context.errors.to_h)
21
9
  str << "\n\n"
22
10
  end
23
11
 
@@ -31,7 +19,7 @@ module Metaractor
31
19
  end
32
20
 
33
21
  str << "Context:\n"
34
- str << Metaractor::FailureOutput.format_hash(context.to_h.reject{|k,_| k == :errors})
22
+ str << Metaractor.format_hash(context.to_h.reject{|k,_| k == :errors})
35
23
  str
36
24
  end
37
25
  end
@@ -3,20 +3,20 @@ module Metaractor
3
3
  class InvalidError < Error; end
4
4
 
5
5
  module HandleErrors
6
- def fail_with_error!(*args)
7
- context.fail_with_error!(*args)
6
+ def fail_with_error!(**args)
7
+ context.fail_with_error!(object: self, **args)
8
8
  end
9
9
 
10
- def fail_with_errors!(*args)
11
- context.fail_with_errors!(*args)
10
+ def fail_with_errors!(**args)
11
+ context.fail_with_errors!(object: self, **args)
12
12
  end
13
13
 
14
- def add_error(*args)
15
- context.add_error(*args)
14
+ def add_error(**args)
15
+ context.add_error(object: self, **args)
16
16
  end
17
17
 
18
- def add_errors(*args)
19
- context.add_errors(*args)
18
+ def add_errors(**args)
19
+ context.add_errors(object: self, **args)
20
20
  end
21
21
 
22
22
  def error_messages
@@ -0,0 +1,46 @@
1
+ module Metaractor
2
+ module Namespace
3
+ # The following code is adapted from rails.
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def module_parent_name
11
+ if defined?(@parent_name)
12
+ @parent_name
13
+ else
14
+ parent_name = name =~ /::[^:]+\z/ ? -$` : nil
15
+ @parent_name = parent_name unless frozen?
16
+ parent_name
17
+ end
18
+ end
19
+
20
+ def module_parent_names
21
+ parents = []
22
+ if module_parent_name
23
+ parents = module_parent_name.split("::")
24
+ end
25
+ parents
26
+ end
27
+
28
+ def i18n_parent_names
29
+ module_parent_names.map {|name| underscore_module_name(name).to_sym }
30
+ end
31
+
32
+ private
33
+
34
+ def underscore_module_name(camel_cased_word)
35
+ return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
36
+ word = camel_cased_word.to_s.gsub("::", "/")
37
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
38
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
39
+ word.tr!("-", "_")
40
+ word.downcase!
41
+ word
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,5 @@
1
+ # Special thanks to the `hashie` and `active_attr` gems for code and inspiration.
2
+
1
3
  module Metaractor
2
4
  module Parameters
3
5
  def self.included(base)
@@ -6,40 +8,92 @@ module Metaractor
6
8
  include Metaractor::HandleErrors
7
9
 
8
10
  class << self
9
- attr_writer :_required_parameters
10
- attr_writer :_optional_parameters
11
- attr_writer :_allow_blank
11
+ attr_writer :requirement_trees
12
12
  end
13
13
 
14
14
  before :remove_blank_values
15
+ before :apply_defaults
15
16
  before :validate_required_parameters
16
17
  end
17
18
  end
18
19
 
20
+ class Parameter
21
+ include Comparable
22
+
23
+ attr_reader :name
24
+
25
+ def initialize(name, **options)
26
+ @name = name.to_sym
27
+ @options = options
28
+ end
29
+
30
+ def <=>(other)
31
+ return nil unless other.instance_of? self.class
32
+ return nil if name == other.name && options != other.options
33
+ self.name.to_s <=> other.name.to_s
34
+ end
35
+
36
+ def [](key)
37
+ @options[key]
38
+ end
39
+
40
+ def dig(name, *names)
41
+ @options.dig(name, *names)
42
+ end
43
+
44
+ def merge!(**options)
45
+ @options.merge!(**options)
46
+ end
47
+
48
+ def to_s
49
+ name.to_s
50
+ end
51
+
52
+ def to_sym
53
+ name
54
+ end
55
+
56
+ protected
57
+ attr_reader :options
58
+ end
59
+
19
60
  module ClassMethods
20
- def _required_parameters
21
- @_required_parameters ||= []
61
+ def parameter(name, **options)
62
+ if param = self.parameter_hash[name.to_sym]
63
+ param.merge!(**options)
64
+ else
65
+ Parameter.new(name, **options).tap do |parameter|
66
+ self.parameter_hash[parameter.name] = parameter
67
+ end
68
+ end
22
69
  end
23
70
 
24
- def required(*params)
25
- self._required_parameters += params
71
+ def parameters(*names, **options)
72
+ names.each do |name|
73
+ parameter(name, **options)
74
+ end
26
75
  end
27
- alias_method :required_parameters, :required
28
76
 
29
- def _optional_parameters
30
- @_optional_parameters ||= []
77
+ def parameter_hash
78
+ @parameters ||= {}
31
79
  end
32
80
 
33
- def optional(*params)
34
- self._optional_parameters += params
81
+ def requirement_trees
82
+ @requirement_trees ||= []
35
83
  end
36
84
 
37
- def _allow_blank
38
- @_allow_blank ||= []
85
+ def required(*params, **options)
86
+ if params.empty?
87
+ tree = options
88
+ self.requirement_trees << tree
89
+ parameters(*parameters_in_tree(tree), required: tree)
90
+ else
91
+ parameters(*params, required: true, **options)
92
+ end
39
93
  end
40
94
 
41
- def allow_blank(*params)
42
- self._allow_blank += params
95
+ def optional(*params, **options)
96
+ parameters(*params, **options)
43
97
  end
44
98
 
45
99
  def validate_parameters(*hooks, &block)
@@ -50,26 +104,74 @@ module Metaractor
50
104
  def validate_hooks
51
105
  @validate_hooks ||= []
52
106
  end
107
+
108
+ def parameters_in_tree(tree)
109
+ if tree.respond_to?(:to_h)
110
+ tree.to_h.values.first.to_a.flat_map {|t| parameters_in_tree(t)}
111
+ else
112
+ [tree]
113
+ end
114
+ end
115
+ end
116
+
117
+ def parameters
118
+ self.class.parameter_hash
119
+ end
120
+
121
+ def requirement_trees
122
+ self.class.requirement_trees
123
+ end
124
+
125
+ def requirement_trees=(trees)
126
+ self.class.requirement_trees=(trees)
53
127
  end
54
128
 
55
129
  def remove_blank_values
56
130
  to_delete = []
57
- context.each_pair do |k,v|
58
- next if self.class._allow_blank.include?(k)
131
+ context.each_pair do |name, value|
132
+ next if parameters.dig(name, :allow_blank)
59
133
 
60
134
  # The following regex is borrowed from Rails' String#blank?
61
- to_delete << k if (v.is_a?(String) && /\A[[:space:]]*\z/ === v) || v.nil?
135
+ to_delete << name if (value.is_a?(String) && /\A[[:space:]]*\z/ === value) || value.nil?
62
136
  end
63
- to_delete.each do |k|
64
- context.delete_field k
137
+
138
+ to_delete.each do |name|
139
+ context.delete_field name
140
+ end
141
+ end
142
+
143
+ def apply_defaults
144
+ parameters.each do |name, parameter|
145
+ next unless parameter[:default]
146
+
147
+ unless context.has_key?(name)
148
+ context[name] = _parameter_default(name)
149
+ end
150
+ end
151
+ end
152
+
153
+ def _parameter_default(name)
154
+ default = self.parameters[name][:default]
155
+
156
+ case
157
+ when default.respond_to?(:call) then instance_exec(&default)
158
+ when default.respond_to?(:dup) then default.dup
159
+ else default
65
160
  end
66
161
  end
67
162
 
68
163
  def validate_required_parameters
69
164
  context.errors ||= []
70
165
 
71
- self.class._required_parameters.each do |param|
72
- require_parameter param
166
+ parameters.each do |name, parameter|
167
+ next if !parameter[:required] ||
168
+ parameter[:required].is_a?(Hash)
169
+
170
+ require_parameter name
171
+ end
172
+
173
+ requirement_trees.each do |tree|
174
+ require_parameter tree
73
175
  end
74
176
 
75
177
  run_validate_hooks
@@ -1,3 +1,3 @@
1
1
  module Metaractor
2
- VERSION = "2.1.1"
2
+ VERSION = "3.0.0"
3
3
  end
data/lib/metaractor.rb CHANGED
@@ -10,6 +10,8 @@ require 'metaractor/chain_failures'
10
10
  require 'metaractor/fail_from_context'
11
11
  require 'metaractor/context_has_key'
12
12
  require 'metaractor/failure_output'
13
+ require 'i18n'
14
+ require 'metaractor/namespace'
13
15
 
14
16
  module Metaractor
15
17
  def self.included(base)
@@ -43,7 +45,8 @@ module Metaractor
43
45
  { module: Metaractor::HandleErrors, method: :include },
44
46
  { module: Metaractor::Parameters, method: :include },
45
47
  { module: Metaractor::RunWithContext, method: :include },
46
- { module: Metaractor::ChainFailures, method: :include }
48
+ { module: Metaractor::ChainFailures, method: :include },
49
+ { module: Metaractor::Namespace, method: :include }
47
50
  ]
48
51
  end
49
52
 
@@ -54,4 +57,24 @@ module Metaractor
54
57
  def self.prepend_module(mod)
55
58
  modules << { module: mod, method: :prepend }
56
59
  end
60
+
61
+ def self.format_hash(hash)
62
+ if @hash_formatter.nil?
63
+ @hash_formatter = default_hash_formatter
64
+ end
65
+
66
+ @hash_formatter.call(hash)
67
+ end
68
+
69
+ def self.default_hash_formatter
70
+ ->(hash){ hash.inspect }
71
+ end
72
+
73
+ def self.hash_formatter
74
+ @hash_formatter
75
+ end
76
+
77
+ def self.hash_formatter=(callable)
78
+ @hash_formatter = callable
79
+ end
57
80
  end
data/metaractor.gemspec CHANGED
@@ -20,8 +20,11 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency 'interactor', '~> 3.1'
22
22
  spec.add_runtime_dependency 'sycamore', '~> 0.3'
23
+ spec.add_runtime_dependency 'i18n', '~> 1.8'
23
24
 
24
25
  spec.add_development_dependency 'bundler', '~> 2'
25
26
  spec.add_development_dependency 'rake', '~> 13.0'
26
27
  spec.add_development_dependency 'rspec', '~> 3.9'
28
+ spec.add_development_dependency 'awesome_print', '~> 1.8'
29
+ spec.add_development_dependency 'pry-byebug', '~> 3.9'
27
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metaractor
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Schlesinger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-09 00:00:00.000000000 Z
11
+ date: 2020-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interactor
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: i18n
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,34 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '3.9'
97
+ - !ruby/object:Gem::Dependency
98
+ name: awesome_print
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.8'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.8'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.9'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.9'
83
125
  description:
84
126
  email:
85
127
  - ryan@outstand.com
@@ -105,6 +147,7 @@ files:
105
147
  - lib/metaractor/fail_from_context.rb
106
148
  - lib/metaractor/failure_output.rb
107
149
  - lib/metaractor/handle_errors.rb
150
+ - lib/metaractor/namespace.rb
108
151
  - lib/metaractor/parameters.rb
109
152
  - lib/metaractor/run_with_context.rb
110
153
  - lib/metaractor/spec.rb