hexx 6.0.3 → 7.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/README.rdoc +63 -48
  4. data/lib/hexx.rb +1 -0
  5. data/lib/hexx/coercible.rb +2 -2
  6. data/lib/hexx/configurable.rb +1 -1
  7. data/lib/hexx/{helpers → creators}/base.rb +11 -15
  8. data/lib/hexx/{helpers → creators}/coercion.rb +8 -8
  9. data/lib/hexx/{helpers → creators}/dependency.rb +8 -8
  10. data/lib/hexx/{helpers → creators}/module_dependency.rb +2 -2
  11. data/lib/hexx/{helpers → creators}/parameter.rb +1 -1
  12. data/lib/hexx/dependable.rb +1 -1
  13. data/lib/hexx/helpers/exceptions.rb +53 -0
  14. data/lib/hexx/helpers/messages.rb +28 -0
  15. data/lib/hexx/helpers/parameters.rb +47 -0
  16. data/lib/hexx/helpers/validations.rb +21 -0
  17. data/lib/hexx/message.rb +79 -0
  18. data/lib/hexx/null.rb +0 -4
  19. data/lib/hexx/service.rb +259 -208
  20. data/lib/hexx/service_invalid.rb +73 -0
  21. data/lib/hexx/version.rb +1 -1
  22. data/spec/hexx/helpers/exceptions_spec.rb +96 -0
  23. data/spec/hexx/helpers/messages_spec.rb +56 -0
  24. data/spec/hexx/helpers/parameters_spec.rb +96 -0
  25. data/spec/hexx/helpers/validations_spec.rb +32 -0
  26. data/spec/hexx/message_spec.rb +83 -0
  27. data/spec/hexx/service_invalid_spec.rb +46 -0
  28. data/spec/hexx/service_spec.rb +41 -242
  29. data/spec/spec_helper.rb +1 -1
  30. data/spec/{initializers → support/initializers}/focus.rb +0 -0
  31. data/spec/{initializers → support/initializers}/garbage_collection.rb +0 -0
  32. data/spec/{initializers → support/initializers}/i18n.rb +0 -0
  33. data/spec/{initializers → support/initializers}/random_order.rb +0 -0
  34. data/spec/{initializers → support/initializers}/rspec.rb +0 -0
  35. data/spec/support/matchers/methods.rb +11 -0
  36. metadata +37 -23
  37. data/lib/hexx/service/invalid.rb +0 -76
  38. data/lib/hexx/service/message.rb +0 -81
  39. data/spec/hexx/service/invalid_spec.rb +0 -52
  40. data/spec/hexx/service/message_spec.rb +0 -85
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ module Hexx
4
+ module Helpers
5
+
6
+ # @api hide
7
+ # The module provides helper methods to add and return service messages.
8
+ module Messages
9
+ extend ActiveSupport::Concern
10
+
11
+ def t(text, options = {})
12
+ return text unless text.is_a? Symbol
13
+ scope = %w(activemodel messages models) << self.class.name.underscore
14
+ I18n.t text, options.merge(scope: scope)
15
+ end
16
+
17
+ def messages
18
+ @messages ||= []
19
+ end
20
+
21
+ attr_writer :messages
22
+
23
+ def add_message(type, text, options = {})
24
+ messages << Hexx::Message.new(type: type, text: t(text, options))
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ module Hexx
4
+
5
+ # @api hide
6
+ # The module contains classes that defines helper methods for the service.
7
+ #
8
+ # Basically those methods are private inside the service. In the helper
9
+ # they are public, allowing them to be testable as a part of the gem's API.
10
+ module Helpers
11
+
12
+ # @api hide
13
+ # The module declares helper methods for managing service object's params.
14
+ module Parameters
15
+ extend ActiveSupport::Concern
16
+
17
+ # @api hide
18
+ # Class helper methods
19
+ module ClassMethods
20
+
21
+ def allow_params(*keys)
22
+ @params = keys.flatten.map(&:to_s)
23
+ fail ArgumentError if @params == []
24
+ params.each { |name| Creators::Parameter.add self, name }
25
+ end
26
+
27
+ private
28
+
29
+ def params
30
+ @params ||= []
31
+ end
32
+ end
33
+
34
+ attr_reader :params
35
+
36
+ def initialize(params = {})
37
+ @params = params.stringify_keys.slice(*class_params)
38
+ end
39
+
40
+ private
41
+
42
+ def class_params
43
+ @class_params ||= self.class.send :params
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ require_relative "messages"
3
+
4
+ module Hexx
5
+ module Helpers
6
+
7
+ # @api hide
8
+ # The module declares instance helper methods to provide validations
9
+ module Validations
10
+ extend ActiveSupport::Concern
11
+
12
+ def validate!
13
+ fail Hexx::ServiceInvalid.new(self) unless valid?
14
+ end
15
+
16
+ def self.included(klass)
17
+ klass.send :include, ActiveModel::Validations
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,79 @@
1
+ module Hexx
2
+
3
+ # A message to be returned by services.
4
+ class Message
5
+ include Comparable
6
+
7
+ # @!attribute [r] type
8
+ # The type of the message
9
+ #
10
+ # @example
11
+ # message = Message.new type: :error, text: "message"
12
+ # message.type = "error"
13
+ #
14
+ # @return [String] The type of the message.
15
+ attr_reader :type
16
+
17
+ # @!attribute [r] text
18
+ # The text of the message
19
+ #
20
+ # @example
21
+ # message = Message.new type: :error, text: "message"
22
+ # message.text = "message"
23
+ #
24
+ # @return [String] The text of the message.
25
+ attr_reader :text
26
+
27
+ # @!scope class
28
+ # @!method new(options)
29
+ # Constructs the message with type and text.
30
+ #
31
+ # @example
32
+ # Message.new type: "success", text: "Object created."
33
+ #
34
+ # @param [Hash] options The list of the message attributes.
35
+ # @option options [String, Symbol] :type The type of the message.
36
+ # @option options [String, Symbol] :text The text of the message.
37
+ # @return [Hexx::Message] The message.
38
+
39
+ # @api hide
40
+ def initialize(type:, text:)
41
+ @type, @text = type.to_s, text.to_s
42
+ end
43
+
44
+ # Distinguishes two messages by type and text.
45
+ #
46
+ # @example
47
+ # a = Message.new(type: "a", text: "a")
48
+ # b = Message.new(type: "a", text: "a")
49
+ # c = Message.new(type: "b", text: "a")
50
+ # d = Message.new(type: "a", text: "b")
51
+ #
52
+ # a == b # => true
53
+ # a == c # => false
54
+ # a == d # => false
55
+ #
56
+ # @param [Object] other The object for the comparison.
57
+ # @return [Boolean] The result of the comparison.
58
+ def ==(other)
59
+ return false unless other.is_a? self.class
60
+ [type, text] == [other.type, other.text]
61
+ end
62
+
63
+ # Compares messages by type and text.
64
+ #
65
+ # @example
66
+ # ab = Message.new(type: "a", text: "b")
67
+ # ba = Message.new(type: "b", text: "a")
68
+ # ab < ba # => true
69
+ #
70
+ # @param [Object] other The object for the comparison.
71
+ # @return [-1, 0, 1] The result of the comparison if the argument is
72
+ # comparable with the message.
73
+ # @return [nil] if the result is incomparable with the message.
74
+ def <=>(other)
75
+ fail ArgumentError unless other.is_a? self.class
76
+ [type, text] <=> [other.type, other.text]
77
+ end
78
+ end
79
+ end
@@ -3,10 +3,6 @@
3
3
  module Hexx
4
4
 
5
5
  # The Null object class.
6
- # @see http://robots.thoughtbot.com/rails-refactoring-example-introduce-null-object
7
- # The intro to null object pattern from Dan Croak.
8
- # @see http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/
9
- # The post of Avdi Grimm on null object falsiness problem.
10
6
  #
11
7
  # Except for some special cases (see examples below) calling any method
12
8
  # returns the +Null+ itself.
@@ -20,186 +20,306 @@ module Hexx
20
20
  # service.run
21
21
  # # => This will call the listener's method #on_found(item).
22
22
  class Service
23
- extend Dependable
24
- include Wisper::Publisher
25
- include ActiveModel::Validations
26
-
27
- # Class helper methods
28
- class << self
29
-
30
- private
31
-
32
- # @api hide
33
- # Returns the list of allowed parameters for service objects.
34
- #
35
- # The parameters are added to the list by the {.allow_params} private
36
- # helper method.
37
- #
38
- # @example
39
- # class Service < Hexx::Service
40
- # allow_params :name
41
- # end
42
- #
43
- # Service.params # => "name"
44
- #
45
- # @return [Array<String>] Whitelist of parameters.
46
- def params
47
- @params ||= []
48
- end
49
-
50
- # Sets a list of allowed parameters for the class constructor and
51
- # defines the corresponding instance attributes.
52
- #
53
- # @example (see Hexx::Service::Parameters.params)
54
- # @param [Array<Symbol, String>] keys The list of allowed parameters.
55
- def allow_params(*keys)
56
- @params = keys.flatten.map(&:to_s)
57
- fail ArgumentError if @params == []
58
- params.each { |name| Helpers::Parameter.add self, name }
59
- end
60
- end
61
-
62
- # @!scope class
63
- # @!method validates(attribute, options)
64
- # Adds a standard validation for the attribute.
65
- # @param [Symbol, String] attribute The name of the attribute to validate.
66
- # @param [Hash] options The list of validation options.
67
- # @see ActiveModel validations {APIdocs}[
68
- # http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates]
69
23
 
70
- # @!scope class
71
- # @!method validate(method, options)
72
- # Adds a custom validation (calls given method).
73
- # @param [Symbol, String] method The name of the validation method.
74
- # @param [Hash] options The list of validation options.
75
- # @see ActiveModel validations {APIdocs}[
76
- # http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validate]
24
+ include Wisper::Publisher
77
25
 
78
- # @!scope class
79
- # @!method new(params = {})
80
- # Constructs the service object with given parameters.
26
+ # @!method subscribe(listener, options = {})
27
+ # @!visibility public
28
+ # Subscribes the listener to service object's notifications.
81
29
  #
82
30
  # @example (see Hexx::Service)
83
- # @param [Hash] params ({}) The parameters of the service object to be
84
- # assigned to the {#params} attribute.
85
- # @return [Hexx::Service] The service object.
31
+ # @param [Object] listener The object that should receive notifications from
32
+ # the service object.
33
+ # @param [Hash] options The list of the subscription options.
34
+ # @option options [Symbol] :prefix The prefix for the listener's callbacks.
35
+ # It defines the prefix to be added to a notification name
36
+ # to provide a corresponding listener method, that should be called by
37
+ # the publisher.
86
38
 
39
+ include Helpers::Parameters
87
40
  # @api hide
88
- # Initializes the service object.
89
- # @param (see Hexx::Service.new)
90
- # @return (see Hexx::Service.new)
91
- def initialize(params = {})
92
- @params = params.dup.stringify_keys.slice(*class_params)
93
- @messages = []
94
- end
41
+ private :params
42
+ private_class_method :allow_params
43
+
44
+ # @!scope class
45
+ # @!method allow_params(*names)
46
+ # @!visibility private
47
+ # Sets a list of allowed parameters for the class constructor and
48
+ # defines the corresponding instance attributes.
49
+ #
50
+ # @example
51
+ # class MyService < Hexx::Service
52
+ # allows_params :name
53
+ # end
54
+ #
55
+ # service = MyService.new name: "name", code: "code"
56
+ # service.send :name # => "name"
57
+ # service.send :params # => { "name" => "name" }
58
+ #
59
+ # @param [Symbol, String, Array<Symbol, String>] names
60
+ # The list of allowed parameters.
95
61
 
96
62
  # @!attribute [r] params
63
+ # @!visibility private
97
64
  # The list of service object parameters.
98
65
  #
99
66
  # The attribute is assigned via the {.new} method options.
100
67
  # On initialization the parameters (keys) are stringified and whitelisted.
101
68
  #
102
- # Allowed parameters should be explicitly declared with the {.allow_params}.
69
+ # Allowed parameters should be explicitly declared via the {.allow_params}
70
+ # private class helper.
103
71
  #
104
- # @example Only whitelisted params are being assigned.
72
+ # @example
105
73
  # class GetItem < Hexx::Service
106
74
  # allow_params :name
107
75
  # end
108
76
  #
109
77
  # service = GetItem.new name: "Олег", family: "Рюрикович"
110
78
  # service.params # => { "name" => "Олег" }
79
+ #
111
80
  # @return [Hash] the service object parameters.
112
81
 
82
+ include Helpers::Messages
83
+ # @api hide
84
+ public :messages
85
+ # @api hide
86
+ private :messages=, :add_message, :t
87
+
113
88
  # @!attribute [r] messages
114
- # The array of service messages (instances of {Hexx::Service::Message})
89
+ # @!visibility public
90
+ # The array of service messages (instances of {Hexx::Message})
115
91
  # with +text+ and +type+ attributes.
116
92
  #
117
- # @example
118
- # class Test < Hexx::Service
93
+ # @note The attribute setter is private!
94
+ #
95
+ # @example The messages can be added by the {#add_message} private helper
96
+ # class EditItem < Hexx::Service
119
97
  # def run
120
- # add_message "info", :ok
98
+ # # ...
99
+ # else
100
+ # add_message "success", "changed"
101
+ # publish :changed, messages
121
102
  # end
122
103
  # end
123
104
  #
124
105
  # service = Test.new
125
- # service.run # adds message
106
+ # service.run
126
107
  # service.messages
127
- # # => [#<Hexx::Service::Message @text="ok" @type="info" >]
108
+ # # => [#<Hexx::Message @type="info" @text="some_text" >]
128
109
  #
129
- # @return [Array<Hexx::Service::Message>] The array of messages.
110
+ # @return [Array<Hexx::Message>] The array of messages.
130
111
 
131
- attr_reader :messages
112
+ # @!scope instance
113
+ # @!method add_message(type, text)
114
+ # @!visibility private
115
+ # Adds the translated message to the {#messages} array.
116
+ #
117
+ # @example
118
+ # class Hello < Hexx::Service
119
+ # def run
120
+ # add_message "success", "Hello!"
121
+ # publish :hello, messages
122
+ # end
123
+ # end
124
+ #
125
+ # hello = Hello.new
126
+ # hello.subscribe listener
127
+ # hello.run
128
+ #
129
+ # # The listener.hello [#<Hexx::Message @type="success", @text="Hello!" >]
130
+ # # will be called.
131
+ #
132
+ # @param [String] type The type of the message: "error", "info", "success"
133
+ # @param [String, Symbol] text The text of the message. The symbol will
134
+ # be translated using the {#t} method.
135
+ # @param [Hash] options The translation options.
136
+ # @return The updated {#messages} array.
132
137
 
133
- # @!scope class
138
+ # @!scope instance
139
+ # @!method t(text, options = {})
134
140
  # @!visibility private
135
- # @!method allow_params(*params)
136
- # Whitelists {#params} and declares a parameter for corresponding keys.
141
+ # Translates given key in current service's scope.
137
142
  #
138
- # @example (see Hexx::Service#params)
143
+ # @note The method uses I18n.t library method.
139
144
  #
140
- # @example Defines corresponding readonly attributes.
141
- # class GetItem < Hexx::Service
142
- # allow_params :name
145
+ # @example Returns a translation if the first argument is a symbol.
146
+ # class PrintHello < Hexx::Service
147
+ # def run
148
+ # puts t(:hello)
149
+ # end
143
150
  # end
144
151
  #
145
- # service = GetItem.new name: "Олег", family: "Рюрикович"
146
- # service.name # => "Олег"
152
+ # object = PrintHello.new
153
+ # object.run
154
+ # # => $ translation not found: en.activemodel.messages.models.test.name
155
+ #
156
+ # @example Returns the string argument.
157
+ # class PrintHello < Hexx::Service
158
+ # def run
159
+ # puts t("hello")
160
+ # end
161
+ # end
147
162
  #
148
- # @param [Array<Symbol, String>] params The list of allowed keys.
163
+ # object = PrintHello.new
164
+ # object.run
165
+ # # => $ name
166
+ #
167
+ # @param [Symbol, String] text The text to be translated.
168
+ # @param [Hash] options ({}) The translation options.
169
+ # @return [String] The translation.
149
170
 
150
- # @!method subscribe(listener, options = {})
151
- # Subscribes the listener to service object's notifications.
152
- # The <tt>:prefix</tt> sets the prefix to be added to a notification name
153
- # to provide a corresponding listener method, that should be called by
154
- # the publisher.
171
+ include Helpers::Validations
172
+ # @api hide
173
+ private :validate!
174
+
175
+ # @!scope class
176
+ # @!method validates(attribute, options)
177
+ # @!visibility private
178
+ # Adds a standard validation for the attribute.
155
179
  #
156
- # @example (see Hexx::Service)
157
- # @param [Object] listener The object that should receive notifications from
158
- # the service object.
159
- # @param [Hash] options The list of the subscription options.
160
- # @option options [Symbol] :prefix The prefix for the listener's callbacks.
180
+ # @param [Symbol, String] attribute The name of the attribute to validate.
181
+ # @param [Hash] options The list of validation options.
182
+ # @see
183
+ # http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates
184
+ # ActiveModel validations APIdocs
161
185
 
162
- # @abstract
163
- # Runs the service object.
186
+ # @!scope class
187
+ # @!method validate(method, options)
188
+ # @!visibility private
189
+ # Adds a custom validation (calls given method).
164
190
  #
165
- # The method does nothing. To be reloaded by a specific service class.
166
- def run
167
- end
191
+ # @param [Symbol, String] method The name of the validation method.
192
+ # @param [Hash] options The list of validation options.
193
+ # @see
194
+ # http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validate
195
+ # ActiveModel validations APIdocs
168
196
 
169
- # Makes private methods with given prefix public.
197
+ # @!scope instance
198
+ # @!method validate!
199
+ # @!visibility private
200
+ # Runs validations and raises <tt>Hexx::ServiceInvalid</tt>
201
+ # when a validation fails.
170
202
  #
171
- # @example Opens private methods.
172
- # def GetItem < Hexx::Service
173
- # private
174
- # def on_success
175
- # publish :success
203
+ # @example (see Hexx::ServiceInvalid)
204
+ #
205
+ # @example Safe usage (recommended) with the {#escape} wrapper.
206
+ # service GetItem < Hexx::Service
207
+ # allow_params :uuid
208
+ # validates :uuid, presence: true
209
+ # def run
210
+ # escape { validate! }
176
211
  # end
177
212
  # end
178
213
  #
179
214
  # service = GetItem.new
180
- # service.respond_to? :on_success
181
- # # => false
215
+ # service.run # => publishes :error notification
182
216
  #
183
- # service_with_callbacks = service.with_callbacks
184
- # service_with_callbacks.respond_to? :on_success
185
- # # => true
217
+ # @raise [Hexx::ServiceInvalid] when the service object isn't valid.
218
+
219
+ include Helpers::Exceptions
220
+ # @api hide
221
+ private :escape, :on_error
222
+ private_class_method :raises
223
+
224
+ # @!scope class
225
+ # @!method raises(exceptions)
226
+ # @!visibility private
227
+ # Declares a list of specific +StandardError+ exceptions.
186
228
  #
187
- # @return [Hexx::Service::WithCallbacks<Hexx::Service>]
188
- # The decorator that allows access to the service's private methods.
189
- def with_callbacks(prefix: nil)
190
- WithCallbacks.new(self, prefix: prefix)
191
- end
229
+ # @example
230
+ # class Service < Hexx::Service
231
+ # raises :NotFound, :NotChanged
232
+ #
233
+ # def run
234
+ # run!
235
+ # rescue NotFound
236
+ # publish :not_found
237
+ # rescue NotChanged
238
+ # publish :not_changed
239
+ # rescue => err
240
+ # # works out any other (unspecified exceptions)
241
+ # publish :error
242
+ # else
243
+ # # works out the main scenario
244
+ # publish :success
245
+ # end
246
+ # end
247
+ #
248
+ # Service.const_defined? :NotFound # => true
249
+ # Service.const_defined? :NotChanged # => true
250
+ #
251
+ # exception = Service::NotFound.new
252
+ # exception.is_a? StandardError # => true
253
+ #
254
+ # @param [String, Symbol, Array<String, Symbol>] exceptions The list of
255
+ # specific +StandardError+ exceptions.
192
256
 
193
- private
257
+ # @!scope instance
258
+ # @!method escape
259
+ # @!visibility private
260
+ # The method re-raises +StandardError+ exceptions as a
261
+ # <tt>Hexx::ServiceInvalid</tt>.
262
+ #
263
+ # * rescues from a +StandardError+ exceptions
264
+ # * adds error message to the service
265
+ # * re-raises the <tt>Hexx::ServiceInvalid</tt> exception
266
+ #
267
+ # @example
268
+ # class GetItem < Hexx::Service
269
+ # def run
270
+ # escape { do_something_unsafe }
271
+ # rescue => err
272
+ # publish :error, err.messages
273
+ # end
274
+ # publish :success
275
+ # end
276
+ # end
277
+ #
278
+ # @yield the block.
279
+ # @raise [Hexx::ServiceInvalid] if the block raised the +StandardError+.
280
+ # @return the value returned by the block.
194
281
 
195
- attr_reader :params
282
+ # @!scope instance
283
+ # @!method on_error(messages)
284
+ # @!visibility private
285
+ # Raises the {Hexx::ServiceInvalid} exception, populated with given
286
+ # messages.
287
+ #
288
+ # @example
289
+ # class EditItem < Hexx::Service
290
+ #
291
+ # allow_params :id, :name
292
+ # # ...
293
+ #
294
+ # def find_item
295
+ # run_service GetItem, :on_item, id: id
296
+ # end
297
+ #
298
+ # def on_item_not_found(*, messages)
299
+ # on_error(messages) # Raises Hexx::ServiceInvalid
300
+ # end
301
+ # end
302
+ #
303
+ # @param [Array<Hexx::ServiceInvalid>] messages The list of error
304
+ # messages to be added to the exception.
305
+ # @raise [Hexx::ServiceInvalid] the exception.
196
306
 
197
- # @api hide
198
- # @return [Array<String>] Whitelist of parameters.
199
- def class_params
200
- self.class.send :params
307
+ # @!scope class
308
+ # @!method new(params = {})
309
+ # Constructs a service object with given parameters.
310
+ #
311
+ # @example (see Hexx::Service)
312
+ # @param [Hash] params ({}) The parameters of the service object to be
313
+ # assigned to the {#params} attribute.
314
+ # @return [Hexx::Service] The service object.
315
+
316
+ # @abstract
317
+ # Runs the service object.
318
+ def run
201
319
  end
202
320
 
321
+ private
322
+
203
323
  # The helper runs another service object and subscribes +self+ for the
204
324
  # service object's notifications.
205
325
  #
@@ -240,98 +360,29 @@ module Hexx
240
360
  service.run
241
361
  end
242
362
 
243
- # @!method escape
244
- #
245
- # The method:
246
- # * rescues +StandardError+ exceptions
247
- # * adds error message to the service
248
- # * re-raises the <tt>Service::Invalid</tt> exception
363
+ # @api hide
364
+ # Makes private methods with given prefix public.
249
365
  #
250
- # @example
251
- # class GetItem < Hexx::Service
252
- # def run
253
- # escape { do_something_unsafe }
254
- # rescue => err
255
- # publish :error, err.messages
256
- # end
366
+ # @example Opens private methods.
367
+ # def GetItem < Hexx::Service
368
+ # private
369
+ # def on_success
257
370
  # publish :success
258
371
  # end
259
372
  # end
260
373
  #
261
- # @yield the block.
262
- # @raise [Hexx::Service::Invalid] if the block raised the +StandardError+.
263
- # @return the value returned by the block.
264
- def escape
265
- yield
266
- rescue Invalid => err
267
- raise err
268
- rescue => err
269
- errors.add :base, err.message
270
- raise Invalid.new(self)
271
- end
272
-
273
- # Translates given key in current service's scope.
274
- #
275
- # @note The method uses I18n.t library method.
276
- #
277
- # @example Returns a translation if the first argument is a symbol.
278
- # class Test < Hexx::Service
279
- # end
280
- # service = Test.new
281
- # service.t :name
282
- # # => "translation not found: en.activemodel.messages.models.test.name"
283
- #
284
- # @example Returns the string argument.
285
- # service = Hexx::Service.new
286
- # service.t "name"
287
- # # => "name"
288
- #
289
- # @param [Symbol, String] text The text to be translated.
290
- # @param [Hash] options The translation options.
291
- # @return [String] The translation.
292
- def t(text, options = {})
293
- return text unless text.is_a? Symbol
294
- scope = %w(activemodel messages models) << self.class.name.underscore
295
- I18n.t text, options.merge(scope: scope)
296
- end
297
-
298
- attr_writer :messages
299
-
300
- # Adds the translated message to the {#messages} array.
301
- # @example (see Service#messages)
302
- # @param [String] type The type of the message ("error", "info", "success")
303
- # @param [String, Symbol] text The text of the message. The symbol will
304
- # be translated using the {#t} method.
305
- # @param [Hash] options The translation options.
306
- # @return The updated {#messages} array.
307
- def add_message(type, text, options = {})
308
- messages << Message.new(type: type, text: t(text, options))
309
- end
310
-
311
- # Runs validations and fails if the service is invalid.
312
- #
313
- # @example (see Hexx::Service::Invalid)
314
- #
315
- # @example Safe usage (recommended) with the {#escape} wrapper.
316
- # service GetItem < Hexx::Service
317
- # allow_params :uuid
318
- # validates :uuid, presence: true
319
- # def run
320
- # escape { validate! }
321
- # end
322
- # end
323
- #
324
374
  # service = GetItem.new
325
- # service.run # => publishes :error notification
375
+ # service.respond_to? :on_success
376
+ # # => false
326
377
  #
327
- # @raise [Hexx::Service::Invalid] when the service object isn't valid.
328
- def validate!
329
- fail Invalid.new(self) unless valid?
330
- end
331
-
332
- def on_error(messages)
333
- messages.map(&:text).each { |text| errors.add :base, text }
334
- fail Invalid.new(self)
378
+ # service_with_callbacks = service.with_callbacks
379
+ # service_with_callbacks.respond_to? :on_success
380
+ # # => true
381
+ #
382
+ # @return [Hexx::Service::WithCallbacks<Hexx::Service>]
383
+ # The decorator that allows access to the service's private methods.
384
+ def with_callbacks(prefix: nil)
385
+ WithCallbacks.new(self, prefix: prefix)
335
386
  end
336
387
  end
337
388
  end