Class: ActiveCall::Base

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Callbacks
Includes:
ActiveModel::Validations, ActiveSupport::Configurable
Defined in:
lib/active_call/base.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.abstract_classObject

Set your class to ‘self.abstract_class = true` if the class is used as a base class and not as a service object. Abstract classes are not meant to be instantiated directly, but rather inherited from. The `call` method doesn’t need to be implemented in abstract classes.

Examples

class YourGem::BaseService < ActiveCall::Base
  self.abstract_class = true
end

class YourGem::SomeResource::CreateService < YourGem::BaseService
  def call
    # Implementation specific to this service.
  end
end


29
30
31
# File 'lib/active_call/base.rb', line 29

def abstract_class
  @abstract_class
end

Instance Attribute Details

#responseObject (readonly)

Returns the value of attribute response.



8
9
10
# File 'lib/active_call/base.rb', line 8

def response
  @response
end

Class Method Details

.abstract_class?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/active_call/base.rb', line 31

def abstract_class?
  @abstract_class == true
end

.callObject

Using ‘call`

Examples

You will get an ‘errors` object when validation fails.

service = YourGem::SomeResource::CreateService.call(message: '')
service.success? # => false
service.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=message, type=blank, options={}>]>
service.errors.full_messages # => ["Message can't be blank"]
service.response # => nil

A ‘response` object on a successful `call` invocation.

service = YourGem::SomeResource::CreateService.call(message: ' bar ')
service.success? # => true
service.response # => {:foo=>"bar"}

And an ‘errors` object if you added errors during the `validate, on: :response` validation.

service = YourGem::SomeResource::CreateService.call(message: 'baz')
service.success? # => false
service.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=message, type=invalid, options={:message=>"cannot be baz"}>]>
service.errors.full_messages # => ["Message cannot be baz"]
service.response # => {:foo=>"baz"}


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/active_call/base.rb', line 63

def call(...)
  service_object = new(...)
  service_object.instance_variable_set(:@bang, false)
  return service_object if service_object.invalid?(except_on: [:request, :response])

  service_object.run_callbacks(:call) do
    next if service_object.is_a?(Enumerable)

    service_object.validate(:request)
    return service_object unless service_object.success?

    service_object.instance_variable_set(:@response, service_object.call)
    service_object.validate(:response)
    return service_object unless service_object.success?
  end

  service_object
end

.call!Object

Using ‘call!`

Examples

An ‘ActiveCall::ValidationError` exception gets raised when validation fails.

begin
  service = YourGem::SomeResource::CreateService.call!(message: '')
rescue ActiveCall::ValidationError => exception
  exception.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=message, type=blank, options={}>]>
  exception.errors.full_messages # => ["Message can't be blank"]
end

A ‘response` object on a successful `call` invocation.

service = YourGem::SomeResource::CreateService.call!(message: ' bar ')
service.success? # => true
service.response # => {:foo=>"bar"}

And an ‘ActiveCall::RequestError` exception gets raised if you added errors during the `validate, on: :response` validation.

begin
  service = YourGem::SomeResource::CreateService.call!(message: 'baz')
rescue ActiveCall::RequestError => exception
  exception.errors # => #<ActiveModel::Errors [#<ActiveModel::Error attribute=message, type=invalid, options={:message=>"cannot be baz"}>]>
  exception.errors.full_messages # => ["Message cannot be baz"]
  exception.response # => {:foo=>"baz"}
end


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/active_call/base.rb', line 112

def call!(...)
  service_object = new(...)
  service_object.instance_variable_set(:@bang, true)

  if service_object.invalid?(except_on: [:request, :response])
    raise ActiveCall::ValidationError, service_object.errors
  end

  service_object.run_callbacks(:call) do
    next if service_object.is_a?(Enumerable)

    service_object.validate(:request)
    raise ActiveCall::RequestError.new(nil, service_object.errors) unless service_object.success?

    service_object.instance_variable_set(:@response, service_object.call)
    service_object.validate(:response)

    unless service_object.success?
      raise ActiveCall::RequestError.new(service_object.response, service_object.errors)
    end
  end

  service_object
end

Instance Method Details

#bang?Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/active_call/base.rb', line 148

def bang?
  !!@bang
end

#callObject

Raises:

  • (NotImplementedError)


152
153
154
155
156
157
# File 'lib/active_call/base.rb', line 152

def call
  return if self.class.abstract_class?

  raise NotImplementedError, 'Subclasses must implement a call method. If this is an abstract base class, set ' \
    '`self.abstract_class = true`.'
end

#success?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/active_call/base.rb', line 138

def success?
  errors.empty?
end

#valid?(context = nil) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
145
146
# File 'lib/active_call/base.rb', line 142

def valid?(context = nil)
  return true if response

  super
end