-
-
Notifications
You must be signed in to change notification settings - Fork 74
/
context.rb
113 lines (95 loc) · 2.75 KB
/
context.rb
1
2
3
4
5
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
require 'arbre/element'
module Arbre
# The Arbre::Context class is the frontend for using Arbre.
#
# The simplest example possible:
#
# html = Arbre::Context.new do
# h1 "Hello World"
# end
#
# html.to_s #=> "<h1>Hello World</h1>"
#
# The contents of the block are instance eval'd within the Context
# object. This means that you lose context to the outside world from
# within the block. To pass local variables into the Context, use the
# assigns param.
#
# html = Arbre::Context.new({:one => 1}) do
# h1 "Your number #{one}"
# end
#
# html.to_s #=> "Your number 1"
#
class Context < Element
# Initialize a new Arbre::Context
#
# @param [Hash] assigns A hash of objecs that you would like to be
# availble as local variables within the Context
#
# @param [Object] helpers An object that has methods on it which will become
# instance methods within the context.
#
# @yield [] The block that will get instance eval'd in the context
def initialize(assigns = {}, helpers = nil, &block)
assigns = assigns || {}
@_assigns = assigns.symbolize_keys
@_helpers = helpers
@_current_arbre_element_buffer = [self]
super(self)
instance_eval &block if block_given?
end
def arbre_context
self
end
def assigns
@_assigns
end
def helpers
@_helpers
end
def indent_level
# A context does not increment the indent_level
super - 1
end
def bytesize
cached_html.bytesize
end
alias :length :bytesize
def respond_to?(method)
super || cached_html.respond_to?(method)
end
# Webservers treat Arbre::Context as a string. We override
# method_missing to delegate to the string representation
# of the html.
def method_missing(method, *args, &block)
if cached_html.respond_to? method
cached_html.send method, *args, &block
else
super
end
end
def current_arbre_element
@_current_arbre_element_buffer.last
end
def with_current_arbre_element(tag)
raise ArgumentError, "Can't be in the context of nil. #{@_current_arbre_element_buffer.inspect}" unless tag
@_current_arbre_element_buffer.push tag
yield
@_current_arbre_element_buffer.pop
end
alias_method :within, :with_current_arbre_element
private
# Caches the rendered HTML so that we don't re-render just to
# get the content lenght or to delegate a method to the HTML
def cached_html
if defined?(@cached_html)
@cached_html
else
html = to_s
@cached_html = html if html.length > 0
html
end
end
end
end