Class: React::RenderingContext

Inherits:
Object
  • Object
show all
Defined in:
lib/react/rendering_context.rb

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.waiting_on_resourcesObject

Returns the value of attribute waiting_on_resources.



4
5
6
# File 'lib/react/rendering_context.rb', line 4

def waiting_on_resources
  @waiting_on_resources
end

Class Method Details

.buildObject



42
43
44
45
46
47
48
# File 'lib/react/rendering_context.rb', line 42

def build
  current = @buffer
  @buffer = []
  return_val = yield @buffer
  @buffer = current
  return_val
end

.delete(element) ⇒ Object Also known as: as_node



50
51
52
53
# File 'lib/react/rendering_context.rb', line 50

def delete(element)
  @buffer.delete(element)
  element
end

.improper_render(message, solution) ⇒ Object



119
120
121
122
# File 'lib/react/rendering_context.rb', line 119

def improper_render(message, solution)
  raise "a component's render method must generate and return exactly 1 element or a string.\n"\
        "    #{message}  #{solution}"
end

.raise_render_error(result) ⇒ Object

heurestically raise a meaningful error based on the situation



108
109
110
111
112
113
114
115
116
117
# File 'lib/react/rendering_context.rb', line 108

def raise_render_error(result)
  improper_render 'A different element was returned than was generated within the DSL.',
                  'Possibly improper use of Element#delete.' if @buffer.count == 1
  improper_render "Instead #{@buffer.count} elements were generated.",
                  'Do you want to wrap your elements in a div?' if @buffer.count > 1
  improper_render "Instead the component #{result} was returned.",
                  "Did you mean #{result}()?" if result.try :reactrb_component?
  improper_render "Instead the #{result.class} #{result} was returned.",
                  'You may need to convert this to a string.'
end

.remove_nodes_from_args(args) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/react/rendering_context.rb', line 64

def remove_nodes_from_args(args)
  args[0].each do |key, value|
    begin
      value.delete if value.is_a?(Element) # deletes Element from buffer
    rescue Exception
    end
  end if args[0] && args[0].is_a?(Hash)
end

.render(name, *args, &block) ⇒ Object



6
7
8
9
10
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
# File 'lib/react/rendering_context.rb', line 6

def render(name, *args, &block)
  was_outer_most = !@not_outer_most
  @not_outer_most = true
  remove_nodes_from_args(args)
  @buffer ||= [] unless @buffer
  if block
    element = build do
      saved_waiting_on_resources = waiting_on_resources
      self.waiting_on_resources = nil
      run_child_block(name.nil?, &block)
      if name
        buffer = @buffer.dup
        React::API.create_element(name, *args) { buffer }.tap do |element|
          element.waiting_on_resources = saved_waiting_on_resources || !!buffer.detect { |e| e.waiting_on_resources if e.respond_to?(:waiting_on_resources) }
          element.waiting_on_resources ||= waiting_on_resources if buffer.last.is_a?(String)
        end
      elsif @buffer.last.is_a? React::Element
        @buffer.last.tap { |element| element.waiting_on_resources ||= saved_waiting_on_resources }
      else
        buffer_s = @buffer.last.to_s
        React::RenderingContext.render(:span) { buffer_s }.tap { |element| element.waiting_on_resources = saved_waiting_on_resources }
      end
    end
  elsif name.is_a? React::Element
    element = name
  else
    element = React::API.create_element(name, *args)
    element.waiting_on_resources = waiting_on_resources
  end
  @buffer << element
  self.waiting_on_resources = nil
  element
ensure
  @not_outer_most = @buffer = nil if was_outer_most
end

.rendered?(element) ⇒ Boolean

Returns:



56
57
58
# File 'lib/react/rendering_context.rb', line 56

def rendered?(element)
  @buffer.include? element
end

.replace(e1, e2) ⇒ Object



60
61
62
# File 'lib/react/rendering_context.rb', line 60

def replace(e1, e2)
  @buffer[@buffer.index(e1)] = e2
end

.run_child_block(is_outer_scope) ⇒ Object

run_child_block gathers the element(s) generated by a child block. for example when rendering this div: div { “hello”.span; “goodby”.span } two child Elements will be generated.

the final value of the block should either be

1 an object that responds to :acts_as_string?
2 a string,
3 an element that is NOT yet pushed on the rendering buffer
4 or the last element pushed on the buffer

in case 1 we render a span in case 2 we automatically push the string onto the buffer in case 3 we also push the Element onto the buffer IF the buffer is empty case 4 requires no special processing

Once we have taken care of these special cases we do a check IF we are in an outer rendering scope. In this case react only allows us to generate 1 Element so we insure that is the case, and also check to make sure that element in the buffer is the element returned



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/react/rendering_context.rb', line 93

def run_child_block(is_outer_scope)
  result = yield
  if result.respond_to?(:acts_as_string?) && result.acts_as_string?
    # hyper-mesh DummyValues respond to acts_as_string, and must
    # be converted to spans INSIDE the parent, otherwise the waiting_on_resources
    # flag will get set in the wrong context
    React::RenderingContext.render(:span) { result.to_s }
  elsif result.is_a?(String) || (result.is_a?(React::Element) && @buffer.empty?)
    @buffer << result
  end
  raise_render_error(result) if is_outer_scope && @buffer != [result]
end