Class: Ballast::Service

Inherits:
Object
  • Object
show all
Defined in:
lib/ballast/service.rb

Overview

A class which implements a common abstraction for services.

Defined Under Namespace

Classes: Response

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(owner = nil) ⇒ Service

Creates a service object.

Parameters:

  • owner (Object|NilClass) (defaults to: nil)

    The owner of the service.



115
116
117
# File 'lib/ballast/service.rb', line 115

def initialize(owner = nil)
  @owner = owner
end

Instance Attribute Details

#ownerObject|NilClass (readonly)

Returns The owner of this service.

Returns:

  • (Object|NilClass)

    The owner of this service.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ballast/service.rb', line 11

class Service
  # A response to a service invocation.
  #
  # @attribute [r] success
  #   @return [Boolean] Whether the invocation was successful or not.
  # @attribute [r] data
  #   @return [Object] The data returned by the operation.
  # @attribute [r] errors
  #   @return [Array] The errors returned by the operation.
  class Response
    attr_reader :success, :data, :errors

    # Creates a new service response.
    #
    # @param success [Boolean] Whether the invocation was successful or not.
    # @param data [Object|NilClass] The data returned by the operation.
    # @param errors [Array|NilClass] The errors returned by the operation.
    # @param error [Object|NilClass] Alias for errors. *Ignored if `errors` is present.*
    def initialize(success = true, data: nil, errors: nil, error: nil)
      errors ||= error.ensure_array

      @success = success.to_boolean
      @data = data
      @errors = errors.ensure_array(no_duplicates: true, compact: true)
    end

    # Returns whether the invocation was successful or not.
    #
    # @return [Boolean] `true` if the service invocation was successful, `false` otherwise.
    def success?
      # TODO@PI: Ignore rubocop on this
      @success
    end
    alias_method :successful?, :success?
    alias_method :succeeded?, :success?

    # Returns whether the invocation failed or not.
    #
    # @return [Boolean] `true` if the service invocation failed, `false` otherwise.
    def fail?
      !@success
    end
    alias_method :failed?, :fail?

    # Returns the first error returned by the operation.
    #
    # @return [Object] The first error returned by the service.
    def error
      @errors.first
    end

    # Converts this response to a AJAX response.
    #
    # @param transport [Object|NilClass] The transport to use for sending. Must respond to `render`, `params`, `request.format` and `performed?`.
    # @return [AjaxResponse] The AJAX response, which will include only the first error.
    def as_ajax_response(transport = nil)
      status, error_message =
        if successful?
          [:ok, nil]
        elsif error.is_a?(Hash)
          [error[:status], error[:error]]
        else
          [:unknown, error]
        end

      AjaxResponse.new(status: status, data: data, error: error_message, transport: transport)
    end
  end

  attr_reader :owner

  # Invokes one of the operations exposed by the service.
  #
  # @param operation [String] The operation to invoke.
  # @param owner [Object|NilClass] The owner of the service.
  # @param raise_errors [Boolean] Whether to raise errors instead of returning a failure.
  # @param params [Hash] The parameters to pass to the service.
  # @param kwargs [Hash] Other modifiers to pass to the service.
  # @param block [Proc] A lambda to pass to the service.
  # @return [Response] The response of the service.
  def self.call(operation = :perform, owner: nil, raise_errors: false, params: {}, **kwargs, &block)
    fail!(status: 501, error: "Unsupported operation #{self}.#{operation}.") unless respond_to?(operation)
    Response.new(true, data: send(operation, owner: owner, params: params, **kwargs, &block))
  rescue Errors::Failure => failure
    handle_failure(failure, raise_errors)
  end

  # Marks the failure of the operation.
  #
  # @param details [Object] The error(s) occurred.
  def self.fail!(details)
    raise(Errors::Failure, details)
  end

  # Marks the failure of the validation of the operation.
  #
  # @param details [Object] The error(s) occurred.
  def self.fail_validation!(details)
    raise(Errors::ValidationFailure, details)
  end

  # Creates a service object.
  #
  # @param owner [Object|NilClass] The owner of the service.
  def initialize(owner = nil)
    @owner = owner
  end

  # Invokes one of the operations exposed by the service.
  #
  # @param operation [String] The operation to invoke.
  # @param owner [Object|NilClass] The owner of the service.
  # @param raise_errors [Boolean] Whether to raise errors instead of returning a failure.
  # @param params [Hash] The parameters to pass to the service.
  # @param kwargs [Hash] Other modifiers to pass to the service.
  # @param block [Proc] A lambda to pass to the service.
  # @return [Response] The response of the service.
  def call(operation = :perform, owner: nil, raise_errors: false, params: {}, **kwargs, &block)
    # PI: Ignore Roodi on this method
    @owner = owner if owner
    fail!(status: 501, error: "Unsupported operation #{self.class}##{operation}.") unless respond_to?(operation)
    Response.new(true, data: send(operation, params: params, **kwargs, &block))
  rescue Errors::Failure => failure
    self.class.send(:handle_failure, failure, raise_errors)
  end

  # Marks the failure of the operation.
  #
  # @param details [Object] The error(s) occurred.
  def fail!(details)
    raise(Errors::Failure, details)
  end

  # Marks the failure of the validation of the operation.
  #
  # @param details [Object] The error(s) occurred.
  def fail_validation!(details)
    raise(Errors::ValidationFailure, details)
  end

  # Handles a failure.
  #
  # @param failure [Failure] The failure to handle.
  # @param raise_errors [Boolean] If `true` it will simply raise the error, otherwise it will return a failure as as Service::Response.
  # @return [Response] A failure response.
  def self.handle_failure(failure, raise_errors)
    raise_errors ? raise(failure) : Response.new(false, error: failure.details)
  end
end

Class Method Details

.call(operation = :perform, owner: nil, raise_errors: false, params: {}, **kwargs, &block) ⇒ Response

Invokes one of the operations exposed by the service.

Parameters:

  • operation (String) (defaults to: :perform)

    The operation to invoke.

  • owner (Object|NilClass) (defaults to: nil)

    The owner of the service.

  • raise_errors (Boolean) (defaults to: false)

    Whether to raise errors instead of returning a failure.

  • params (Hash) (defaults to: {})

    The parameters to pass to the service.

  • kwargs (Hash)

    Other modifiers to pass to the service.

  • block (Proc)

    A lambda to pass to the service.

Returns:

  • (Response)

    The response of the service.



91
92
93
94
95
96
# File 'lib/ballast/service.rb', line 91

def self.call(operation = :perform, owner: nil, raise_errors: false, params: {}, **kwargs, &block)
  fail!(status: 501, error: "Unsupported operation #{self}.#{operation}.") unless respond_to?(operation)
  Response.new(true, data: send(operation, owner: owner, params: params, **kwargs, &block))
rescue Errors::Failure => failure
  handle_failure(failure, raise_errors)
end

.fail!(details) ⇒ Object

Marks the failure of the operation.

Parameters:

  • details (Object)

    The error(s) occurred.

Raises:



101
102
103
# File 'lib/ballast/service.rb', line 101

def self.fail!(details)
  raise(Errors::Failure, details)
end

.fail_validation!(details) ⇒ Object

Marks the failure of the validation of the operation.

Parameters:

  • details (Object)

    The error(s) occurred.

Raises:



108
109
110
# File 'lib/ballast/service.rb', line 108

def self.fail_validation!(details)
  raise(Errors::ValidationFailure, details)
end

.handle_failure(failure, raise_errors) ⇒ Response

Handles a failure.

Parameters:

  • failure (Failure)

    The failure to handle.

  • raise_errors (Boolean)

    If true it will simply raise the error, otherwise it will return a failure as as Service::Response.

Returns:



156
157
158
# File 'lib/ballast/service.rb', line 156

def self.handle_failure(failure, raise_errors)
  raise_errors ? raise(failure) : Response.new(false, error: failure.details)
end

Instance Method Details

#call(operation = :perform, owner: nil, raise_errors: false, params: {}, **kwargs, &block) ⇒ Response

Invokes one of the operations exposed by the service.

Parameters:

  • operation (String) (defaults to: :perform)

    The operation to invoke.

  • owner (Object|NilClass) (defaults to: nil)

    The owner of the service.

  • raise_errors (Boolean) (defaults to: false)

    Whether to raise errors instead of returning a failure.

  • params (Hash) (defaults to: {})

    The parameters to pass to the service.

  • kwargs (Hash)

    Other modifiers to pass to the service.

  • block (Proc)

    A lambda to pass to the service.

Returns:

  • (Response)

    The response of the service.



128
129
130
131
132
133
134
135
# File 'lib/ballast/service.rb', line 128

def call(operation = :perform, owner: nil, raise_errors: false, params: {}, **kwargs, &block)
  # PI: Ignore Roodi on this method
  @owner = owner if owner
  fail!(status: 501, error: "Unsupported operation #{self.class}##{operation}.") unless respond_to?(operation)
  Response.new(true, data: send(operation, params: params, **kwargs, &block))
rescue Errors::Failure => failure
  self.class.send(:handle_failure, failure, raise_errors)
end

#fail!(details) ⇒ Object

Marks the failure of the operation.

Parameters:

  • details (Object)

    The error(s) occurred.

Raises:



140
141
142
# File 'lib/ballast/service.rb', line 140

def fail!(details)
  raise(Errors::Failure, details)
end

#fail_validation!(details) ⇒ Object

Marks the failure of the validation of the operation.

Parameters:

  • details (Object)

    The error(s) occurred.

Raises:



147
148
149
# File 'lib/ballast/service.rb', line 147

def fail_validation!(details)
  raise(Errors::ValidationFailure, details)
end