metaractor 2.1.1 → 3.0.0

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