Class: Shaven::Transformer

Inherits:
Object show all
Defined in:
lib/shaven/transformer.rb,
lib/shaven/transformers/auto.rb,
lib/shaven/transformers/list.rb,
lib/shaven/transformers/dummy.rb,
lib/shaven/transformers/context.rb,
lib/shaven/transformers/condition.rb,
lib/shaven/transformers/text_or_node.rb,
lib/shaven/transformers/reverse_condition.rb

Defined Under Namespace

Classes: Auto, Condition, Context, Dummy, List, ReverseCondition, TextOrNode

Constant Summary collapse

Base =

Just sugar to not using self in inheritance definition.

self
CALLERS =

This is chain containing list of DOM caller arguments and related transformers. All of them will be sequentially applied to each node in your template. Order is important because some of them allow to keep going with other transformations after they are applied, other doesn’t allow that.

[
  ['dummy',  Dummy],
  ['if',     Condition],
  ['unless', ReverseCondition],
  [nil,      Auto]
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, value, scope) ⇒ Transformer

Returns a new instance of Transformer.



86
87
88
# File 'lib/shaven/transformer.rb', line 86

def initialize(name, value, scope)
  @name, @value, @scope = name, value, scope
end

Instance Attribute Details

#nameObject (readonly)

Name of the presenters method/key from which value has been extracted.



80
81
82
# File 'lib/shaven/transformer.rb', line 80

def name
  @name
end

#scopeObject (readonly)

Transformation context scope.



84
85
86
# File 'lib/shaven/transformer.rb', line 84

def scope
  @scope
end

#valueObject (readonly)

Value extracted from presenter.



82
83
84
# File 'lib/shaven/transformer.rb', line 82

def value
  @value
end

Class Method Details

.apply!(scope) ⇒ Object

Applies each transformers within scope, to all children of represented document’s node. Transformations are applied only for element nodes.



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/shaven/transformer.rb', line 52

def apply!(scope)
  scope.node.children.each { |child|
    if child.elem?
      extra_scope = apply_each(scope.with(child))
      scope.unshift(extra_scope) if extra_scope
      apply!(scope)
      scope.shift if extra_scope
    end
  }
  nil
end

.apply_each(scope, &block) ⇒ Object

Goes through callers chain and tries to apply all matching transformers within given scope. If scope for children should be combined/modified then it returns new scope for later usage, otherwise nil will be returned.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/shaven/transformer.rb', line 35

def apply_each(scope, &block)
  callers.each { |(name,trans)|
    if key = scope.node.delete(name)
      value = trans.find_value(scope, key).to_shaven
      
      if trans.can_be_transformed?(value)
        transformer = trans.new(key, value, scope)
        extra_scope = transformer.transform!
        return extra_scope unless transformer.allow_continue?
      end
    end
  }
  nil
end

.callersObject

Returns list of callers with full names. Names are combined with configuration setting in Shaven.caller_key.



25
26
27
28
29
30
# File 'lib/shaven/transformer.rb', line 25

def callers
  @callers ||= CALLERS.map { |(name,trans)|
    name = [Shaven.caller_key, name].compact.join(':')
    [name,trans]
  }
end

.can_be_transformed?(value) ⇒ Boolean

This method contains set of conditions which tells if given value can be used to transformation on current node. Each transformer should override this method if has such extra requirements.

Returns:

  • (Boolean)


67
68
69
# File 'lib/shaven/transformer.rb', line 67

def can_be_transformed?(value)
  true
end

.find_value(scope, key) ⇒ Object

Transformers can load values from scope in differen ways, so this method allows to define such own way within each trasformer. By default it just picks up specified key from given scope.



74
75
76
# File 'lib/shaven/transformer.rb', line 74

def find_value(scope, key)
  scope[key]
end

Instance Method Details

#allow_continue?Boolean

If this method returns true then transformers left in chain gonna be applied to node within current scope, otherwise transformation chain will be broken. By default continuing after one transformation is not allowed.

Returns:

  • (Boolean)


98
99
100
# File 'lib/shaven/transformer.rb', line 98

def allow_continue?
  false
end

#nodeObject

Just shortcut for scope.node.



91
92
93
# File 'lib/shaven/transformer.rb', line 91

def node
  scope.node
end

#transform!Object

This method should contain all transformation directives. If scope for children nodes should be modified then method should return extra hash/scope which will be temporary combined with current one, otherwise returns nil.

Raises:

  • (NotImplementedError)


105
106
107
# File 'lib/shaven/transformer.rb', line 105

def transform!
  raise NotImplementedError, "You have to implement #transform! in your transformer"
end