Class: ServiceOperation::Context

Inherits:
OpenStruct
  • Object
show all
Defined in:
lib/service_operation/context.rb

Overview

Context for an Operation

Constant Summary collapse

CALLER_NAME_REGEXP =
/`(rescue in |)([^']*)'$/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.build(context = {}) ⇒ Object

Class Methods



14
15
16
# File 'lib/service_operation/context.rb', line 14

def self.build(context = {})
  self === context ? context : new(context) # rubocop:disable Style/CaseEquality
end

Instance Method Details

#as_json(*args) ⇒ Object

Fixes stack loop issue with OpenStruct



24
25
26
# File 'lib/service_operation/context.rb', line 24

def as_json(*args)
  to_h.as_json(*args)
end

#coerce_if(*klasses) ⇒ Object

Use in the Operation class to create eager loading objects:

Operation.call(record: 'something').record == <Model name='something'>

Examples:

def Operation#record
  context.coerce_if(Integer, String) { |name| Model.find_by_param(name) }
end


43
44
45
46
47
48
# File 'lib/service_operation/context.rb', line 43

def coerce_if(*klasses)
  field = klasses.shift if klasses.first.is_a?(Symbol)
  field ||= caller(1..1).first[CALLER_NAME_REGEXP, 2] # method name fetch was called from
  self[field] = yield(self[field]) if klasses.any? { |k| self[field].is_a?(k) }
  self[field]
end

#fail!(context = {}) ⇒ Object

Raises:



28
29
30
31
32
33
# File 'lib/service_operation/context.rb', line 28

def fail!(context = {})
  context.each { |k, v| send("#{k}=", v) }
  @failure = true

  raise Failure, self
end

#failure?Boolean

Returns:

  • (Boolean)


106
107
108
# File 'lib/service_operation/context.rb', line 106

def failure?
  @failure || false
end

#fetch(*args) ⇒ Object

Examples:

fetch(:field, 'value')
fetch(:field) { 'value' }

will infer field name from enclosing method name

def enclosing_method
  context.fetch { 'value' }
end
def enclosing_method
  context.fetch 'value'
end


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
# File 'lib/service_operation/context.rb', line 62

def fetch(*args)
  if !block_given? && args.length == 1 # context.fetch 'value'
    new_value = args.first
  else
    field, new_value = args
  end

  field ||= caller(1..1).first[CALLER_NAME_REGEXP, 2] # method name fetch was called from

  # field is already set
  value = send(field)
  return value if value

  # context.fetch { block }
  if block_given?
    begin
      value ||= yield
    rescue StandardError => e
      # apply if this context to the field, if this is first instance of this error being raised
      self[field] = e.context if e.respond_to?(:context) &&
                                 e.context.is_a?(self.class) &&
                                 e.context != self &&
                                 e.context.not_yet_raised

      raise e
    end
  end

  value ||= new_value

  self[field] = value

  value
end

#not_yet_raisedtrue, false

Returns first call returns false, after that true.

Returns:

  • (true, false)

    first call returns false, after that true.



98
99
100
101
102
103
104
# File 'lib/service_operation/context.rb', line 98

def not_yet_raised
  if @already_raised
    false
  else
    @already_raised = true
  end
end

#success?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/service_operation/context.rb', line 110

def success?
  !failure?
end

#to_h(*args) ⇒ Object



114
115
116
117
118
119
120
# File 'lib/service_operation/context.rb', line 114

def to_h(*args)
  if args.any?
    super().slice(*args)
  else
    super()
  end
end