Class: Mediator

Inherits:
Object
  • Object
show all
Extended by:
Registry
Defined in:
lib/mediator.rb,
lib/mediator/errors.rb,
lib/mediator/parser.rb,
lib/mediator/registry.rb,
lib/mediator/renderer.rb,
lib/mediator/processor.rb

Overview

Can’t we all just get along? Mediators should subclass and implement ‘parse!` and `render!`.

Defined Under Namespace

Modules: Registry Classes: Error, Parser, Processor, Renderer

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Registry

[], accept, for, mediate, register, registries, registry

Constructor Details

#initialize(subject, context = nil) ⇒ Mediator

Create a new mediator with a ‘subject` and a mediation `context`. If the context is a Mediator, it will be set as this instance’s parent and its context will be reused.



32
33
34
35
36
37
38
39
40
# File 'lib/mediator.rb', line 32

def initialize subject, context = nil
  @context = context
  @subject = subject

  if Mediator === context
    @parent  = @context
    @context = @parent.context
  end
end

Instance Attribute Details

#contextObject (readonly)

State information availble during ‘parse` and `render`. This is often an application-specific object that provides authentication and authorization data, but it can be just about anything.



16
17
18
# File 'lib/mediator.rb', line 16

def context
  @context
end

#parentObject (readonly)

An optional parent mediator. Used during nested mediation: See ‘obj`, etc.



21
22
23
# File 'lib/mediator.rb', line 21

def parent
  @parent
end

#subjectObject (readonly)

The subject of this mediation. A rich(er) domain object that needs to be translated back and forth.



26
27
28
# File 'lib/mediator.rb', line 26

def subject
  @subject
end

Instance Method Details

#construct(name) ⇒ Object

Called during ‘get` if `subject` doesn’t have a value for ‘name` during parsing. Subclasses can override to provide factories for dependent attributes. The default implementation returns `nil`.



46
47
# File 'lib/mediator.rb', line 46

def construct name
end

#data_has?(data, name) ⇒ Boolean

True if data can return a value for name

Returns:

  • (Boolean)


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

def data_has? data, name
  data.has_key?(name) || data.has_key?(name.to_s)
end

#get(name) ⇒ Object

Gets the ‘name` property from `subject`. The default implementation calls the `name` method if it exists.



155
156
157
158
159
160
# File 'lib/mediator.rb', line 155

def get name
  value = subject.send name if subject.respond_to? name
  value = construct name    if value.nil?

  getting name, value       unless value.nil?
end

#getting(name, value) ⇒ Object

Called when getting ‘name` from `subject`. Can be used to transform outgoing values, e.g., turning Time objects into epoch seconds. The default implementation returns `value` unchanged.



166
167
168
# File 'lib/mediator.rb', line 166

def getting name, value
  value
end

#incoming(data) ⇒ Object

Called before passing ‘data` to `parse`. Subclasses can override to transform raw incoming data. The default implementation returns `data` unchanged.



53
54
55
# File 'lib/mediator.rb', line 53

def incoming data
  data
end

#inside?(subject) ⇒ Boolean

Is ‘subject` the subject of one of the ancestral mediators?

Returns:

  • (Boolean)


59
60
61
# File 'lib/mediator.rb', line 59

def inside? subject
  parent && (parent.subject == subject || parent.inside?(subject))
end

#nested?(candidate = nil, &block) ⇒ Boolean

Is this mediator nested inside a ‘parent`?

Returns:

  • (Boolean)


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

def nested? candidate = nil, &block
  if candidate && block
    raise Error, "Can't provide both a candidate and a block."
  end

  if !parent
    false
  elsif !candidate && !block
    true
  elsif candidate  && (candidate === parent.subject)
    true
  elsif block && block[parent]
    true
  else
    parent.nested? candidate, &block
  end
end

#outgoing(data) ⇒ Object

Called after rendering. Subclasses can override to transform raw outgoing data. The default implementation returns ‘data` unchanged.



87
88
89
# File 'lib/mediator.rb', line 87

def outgoing data
  data
end

#parse(data) ⇒ Object

Folds, spindles, and mutilates ‘data`, then applies to `subject` and returns it. Subclasses should generally override `parse!` instead of this method.



95
96
97
98
# File 'lib/mediator.rb', line 95

def parse data
  parse! parser incoming data
  subject
end

#parse!(parser) ⇒ Object

The actual parse implementation. Subclasses should override and consistently call ‘super`.

Raises:

  • (NotImplementedError)


103
104
105
# File 'lib/mediator.rb', line 103

def parse! parser
  raise NotImplementedError
end

#parser(data) ⇒ Object

Construct a parser instance for ‘data`. The parser will be passed to the Mediator’s ‘parse!` method. The default implementation returns a new instance of Mediator::Parser.



111
112
113
# File 'lib/mediator.rb', line 111

def parser data
  Mediator::Parser.new self, data
end

#renderObject

Create a more primitive representation of ‘subject`. Subclasses should generally override `render!` instead of this method.



118
119
120
121
122
123
# File 'lib/mediator.rb', line 118

def render
  r = renderer
  render! r

  outgoing r.data
end

#render!(renderer) ⇒ Object

The actual render implementation. Subclasses should override and consistently call ‘super`.

Raises:

  • (NotImplementedError)


128
129
130
# File 'lib/mediator.rb', line 128

def render! renderer
  raise NotImplementedError
end

#rendererObject

Construct a renderer instance. The renderer will be passed to the Mediator’s ‘render!` method. The default implementation returns a new instance of Mediator::Renderer.



136
137
138
# File 'lib/mediator.rb', line 136

def renderer
  Mediator::Renderer.new self
end

#set(name, value) ⇒ Object

Set ‘name` to `value` on `subject`. The default implementation calls a matching mutator method.



173
174
175
# File 'lib/mediator.rb', line 173

def set name, value
  subject.send "#{name}=", setting(name, value)
end

#setting(name, value) ⇒ Object

Called when setting ‘name` to `value` on `subject`. Can be used to transform incoming values, e.g., trimming all strings. The default implementation returns `value` unchanged.



181
182
183
# File 'lib/mediator.rb', line 181

def setting name, value
  value
end

#subject_has?(name) ⇒ Boolean

True if subject can construct a value for name

Returns:

  • (Boolean)


142
143
144
# File 'lib/mediator.rb', line 142

def subject_has? name
  subject.respond_to?(name) || subject.respond_to?(name.to_s)
end