Class: Garterbelt::View

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

Direct Known Subclasses

Page

Constant Summary collapse

CONTENT_TAGS =
[
  'a', 'abbr', 'acronym', 'address', 
  'b', 'bdo', 'big', 'blockquote', 'body', 'button', 
  'caption', 'center', 'cite', 'colgroup',
  'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em',
  'embed',
  'fieldset', 'form', 'frameset',
  'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'i',
  'iframe', 'ins', 'kbd', 'label', 'legend', 'li', 'map',
  'noframes', 'noscript', 
  'object', 'ol', 'optgroup', 'option', 'p', 'param', 
  'q', 's',
  'samp', 'select', 'small', 'span',
  'strong', 'sub', 'sup',
  'table', 'tbody', 'td', 'tfoot', 
  'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var'
]
NON_ESCAPE_TAGS =
['code', 'pre', 'script', 'style']
CLOSED_TAGS =
['area', 'br', 'col', 'frame', 'hr', 'img', 'input']
HEAD_TAGS =
['base', 'meta', 'link']
MINIFIED_TAGS =
['textarea']
CACHE_DETAIL_DEFAULT =
'default'

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}, &block) ⇒ View

Returns a new instance of View.



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
# File 'lib/view.rb', line 6

def initialize(opts={}, &block)
  self.initialization_options =  opts
  self._buffer = []
  self._level =  initialization_options.delete(:_level) || 0
  self.render_style = initialization_options.delete(:style) || :pretty
  self.output = ""
  self._escape = true
  self.block = block if block_given?
  
  self._curator = initialization_options.delete(:_curator) || self
  
  params = self.class.default_variables.merge(opts)
  keys = params.keys
  
  unless (self.class.required - keys).empty?
    raise ArgumentError, "#{(self.class.required - keys).inspect} required as an initialization option"
  end
  
  if self.class.selective_require && keys != self.class.required
    raise ArgumentError, "Allowed initalization options are only #{self.class.required.inspect}"
  end
  
  params.each do |key, value|
    self.class.add_accessor(key) unless respond_to?(key)
    instance_variable_set "@#{key}", value
  end
end

Class Attribute Details

.cache_key_baseObject



398
399
400
# File 'lib/view.rb', line 398

def self.cache_key_base
  @cache_key_base ||= self.to_s.underscore
end

.cache_store_keyObject



386
387
388
# File 'lib/view.rb', line 386

def self.cache_store_key
  @cache_store_key ||= :default
end

.default_content_methodObject



291
292
293
# File 'lib/view.rb', line 291

def self.default_content_method
  @default_content_method ||= :content
end

.default_render_styleObject



287
288
289
# File 'lib/view.rb', line 287

def self.default_render_style
  @default_render_style ||= :pretty
end

.requiredObject



55
56
57
# File 'lib/view.rb', line 55

def self.required
  @required ||= []
end

.selective_requireObject

Returns the value of attribute selective_require.



52
53
54
# File 'lib/view.rb', line 52

def selective_require
  @selective_require
end

Instance Attribute Details

#_bufferObject

Returns the value of attribute _buffer.



3
4
5
# File 'lib/view.rb', line 3

def _buffer
  @_buffer
end

#_curatorObject

Returns the value of attribute _curator.



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

def _curator
  @_curator
end

#_escapeObject

Returns the value of attribute _escape.



3
4
5
# File 'lib/view.rb', line 3

def _escape
  @_escape
end

#_levelObject

Returns the value of attribute _level.



3
4
5
# File 'lib/view.rb', line 3

def _level
  @_level
end

#blockObject

Returns the value of attribute block.



3
4
5
# File 'lib/view.rb', line 3

def block
  @block
end

#cache_key_baseObject



402
403
404
# File 'lib/view.rb', line 402

def cache_key_base
  @cache_key_base ||= self.class.cache_key_base
end

#cache_store_keyObject



390
391
392
# File 'lib/view.rb', line 390

def cache_store_key
  @cache_store_key ||= self.class.cache_store_key
end

#initialization_optionsObject

Returns the value of attribute initialization_options.



3
4
5
# File 'lib/view.rb', line 3

def initialization_options
  @initialization_options
end

#outputObject

Returns the value of attribute output.



3
4
5
# File 'lib/view.rb', line 3

def output
  @output
end

#render_styleObject

Returns the value of attribute render_style.



3
4
5
# File 'lib/view.rb', line 3

def render_style
  @render_style
end

Class Method Details

.accessoriesObject



70
71
72
# File 'lib/view.rb', line 70

def self.accessories
  @accessories ||= superclass? ? superclass.accessories.dup : []
end

.add_accessor(key) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/view.rb', line 59

def self.add_accessor key
  key = key.to_s
  return if accessories.include?(key)
  if (instance_methods - Object.instance_methods).include?(key)
    raise ArgumentError, ":#{key} cannot be a required variable because it maps to an existing method"
  end
  
  accessories << key.to_s
  attr_accessor key
end

.build_accessorsObject



108
109
110
111
112
# File 'lib/view.rb', line 108

def self.build_accessors
  required.each do |m|
    add_accessor m
  end
end

.default_variablesObject



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

def self.default_variables
  @default_variables ||= superclass? ? superclass.default_variables.dup : Hash.new
end

.render(opts = {}, &block) ⇒ Object



345
346
347
348
349
350
# File 'lib/view.rb', line 345

def self.render(opts={}, &block)
  content_method = opts.delete(:method)
  view = block_given? ? new(opts, &block) : new(opts)
  output = content_method ? view.render(content_method) : view.render
  output
end

.requires(*args) ⇒ Object Also known as: needs



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/view.rb', line 86

def self.requires *args
  if args.last.is_a?(Hash) 
    self.default_variables.merge!(args.pop) 
    args += default_variables.keys.map{ |x| x.to_sym }
  end 
  
  args = super_required + args  
  self.required += args.uniq
  build_accessors
  required
end

.requires_only(*args) ⇒ Object Also known as: needs_only



98
99
100
101
# File 'lib/view.rb', line 98

def self.requires_only(*args)
  self.selective_require = true
  requires(*args)
end

.super_requiredObject



78
79
80
# File 'lib/view.rb', line 78

def self.super_required
  superclass? ? superclass.required : []
end

.superclass?Boolean

Returns:

  • (Boolean)


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

def self.superclass?
  @superclassed ||= superclass.respond_to?( :required )
end

Instance Method Details

#add_to_buffer(renderer) ⇒ Object

TAG HELPERS ———————–



116
117
118
119
# File 'lib/view.rb', line 116

def add_to_buffer(renderer)
  _buffer << renderer
  renderer
end

#cache(key, opts = {}, &block) ⇒ Object



413
414
415
416
# File 'lib/view.rb', line 413

def cache(key, opts={}, &block)
  opts = opts.merge(:key => cache_key(key), :view => _curator)
  add_to_buffer Cache.new(opts, &block)
end

#cache_key(detail = CACHE_DETAIL_DEFAULT) ⇒ Object



408
409
410
411
# File 'lib/view.rb', line 408

def cache_key(detail = CACHE_DETAIL_DEFAULT)
  detail ||= CACHE_DETAIL_DEFAULT
  "#{cache_key_base}_#{detail}"
end

#cache_storeObject



394
395
396
# File 'lib/view.rb', line 394

def cache_store
  @cache ||= Garterbelt.cache(cache_store_key)
end

#call_blockObject



329
330
331
# File 'lib/view.rb', line 329

def call_block
  block.call if block
end

#closed_tag(type, *args) ⇒ Object



130
131
132
# File 'lib/view.rb', line 130

def closed_tag(type, *args)
  add_to_buffer ClosedTag.new(parse_tag_arguments(type, args))
end

#comment_tag(content) ⇒ Object



175
176
177
# File 'lib/view.rb', line 175

def comment_tag(content)
  add_to_buffer Comment.new(:view => _curator, :content => content)
end

#compact_tag(type, *args, &block) ⇒ Object



145
146
147
148
149
150
151
152
153
154
# File 'lib/view.rb', line 145

def compact_tag(type, *args, &block)
  args << {} unless args.last.is_a?(Hash)
  args.last[:render_style] = :compact
    
  if block_given?
    tag(type, *args, &block)
  else
    tag(type, *args)
  end
end

#contentObject

RENDERING ————————-

Raises:

  • (NotImplementedError)


279
280
281
# File 'lib/view.rb', line 279

def content
  raise NotImplementedError, "Implement #content in #{self.class}!"
end

#curated?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/view.rb', line 45

def curated?
  _curator === self
end

#doctype(type = :transitional) ⇒ Object



179
180
181
# File 'lib/view.rb', line 179

def doctype(type=:transitional)
  add_to_buffer Doctype.new(:view => _curator, :type => type)
end


273
274
275
# File 'lib/view.rb', line 273

def javascript_link(path)
  script(:src => "#{path}.js", 'type' => "text/javascript")
end

#non_escape_tag(*args, &block) ⇒ Object



134
135
136
137
138
139
140
141
142
143
# File 'lib/view.rb', line 134

def non_escape_tag(*args, &block)
  if _escape
    _curator._escape = false
    t = block_given? ? tag(*args, &block) : tag(*args)
    _curator._escape = true
    t
  else
    block_given? ? tag(*args, &block) : tag(*args)
  end
end

#page_title(*args, &block) ⇒ Object



265
266
267
# File 'lib/view.rb', line 265

def page_title(*args, &block)
  block_given? ? tag(:title, *args, &block) : tag(:title, *args)
end

#parse_tag_arguments(type, args) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/view.rb', line 188

def parse_tag_arguments(type, args)
  opts = {:type => type, :view => _curator}
  if args.size == 2
    opts[:content] = args.shift
    opts[:attributes] = args.first
  else
    if args.first.is_a?(Hash)
      opts[:attributes] = args.first
    else
      opts[:content] = args.first
    end
  end
  opts[:render_style] = opts[:attributes].delete(:render_style) if opts[:attributes] && opts[:attributes][:render_style]
  opts
end

#partial(*args, &block) ⇒ Object Also known as: widget



352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/view.rb', line 352

def partial(*args, &block)
  view = if (klass = args.first).is_a?(Class)
    args.shift
    partial_opts = args.shift || {}
    available_opts = self.class.default_variables.merge(initialization_options)
    opts = if klass.selective_require
      klass.required.each do |key|
        partial_opts[key] ||= available_opts[key]
      end
      partial_opts
    else
      available_opts.merge(partial_opts)
    end
    klass.new(opts)
  else
    args.first
  end
  view.block = block if block
  view._curator = _curator
  self._buffer << view
  view
end

#raw_text(content) ⇒ Object Also known as: raw, rawtext



162
163
164
165
166
167
168
169
170
171
# File 'lib/view.rb', line 162

def raw_text(content)
  if _escape
    _curator._escape = false
    t = text(content)
    _curator._escape = true
    t
  else
    text(content)
  end
end

#render(*args) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/view.rb', line 295

def render(*args)
  if args.first.is_a?(Hash)
    initialization_options = args.shift
    content_method = initialization_options[:method]
  else
    content_method = args.shift
    initialization_options = args.shift || {}
  end
  
  content_method ||= self.class.default_content_method
  self.render_style = initialization_options[:style] || self.class.default_render_style
  
  self.output = "" if curated?
  
  if block
    send(content_method, &block)
  else
    send(content_method)
  end
  
  render_buffer
  output
end

#render_blockObject



322
323
324
325
326
327
# File 'lib/view.rb', line 322

def render_block
  return output unless block
  block.call
  render_buffer
  output
end

#render_bufferObject



333
334
335
336
337
338
339
340
341
342
343
# File 'lib/view.rb', line 333

def render_buffer
  array = _buffer.dup
  _buffer.clear
  array.each do |item|
    if item.respond_to?(:render)
      item.render
    else
      output << item.to_s
    end
  end
end


269
270
271
# File 'lib/view.rb', line 269

def stylesheet_link(path)
  _link(:rel => "stylesheet", 'type' => "text/css", :href => "#{path}.css")
end

#tag(type, *args, &block) ⇒ Object



121
122
123
124
125
126
127
128
# File 'lib/view.rb', line 121

def tag(type, *args, &block)
  t = if block_given?
    ContentTag.new(parse_tag_arguments(type, args), &block)
  else
    ContentTag.new(parse_tag_arguments(type, args))
  end
  add_to_buffer t
end

#text(content) ⇒ Object Also known as: h



156
157
158
# File 'lib/view.rb', line 156

def text(content)
  add_to_buffer Text.new(:view => _curator, :content => content)
end

#to_htmlObject



320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/view.rb', line 320

def render(*args)
  if args.first.is_a?(Hash)
    initialization_options = args.shift
    content_method = initialization_options[:method]
  else
    content_method = args.shift
    initialization_options = args.shift || {}
  end
  
  content_method ||= self.class.default_content_method
  self.render_style = initialization_options[:style] || self.class.default_render_style
  
  self.output = "" if curated?
  
  if block
    send(content_method, &block)
  else
    send(content_method)
  end
  
  render_buffer
  output
end

#to_sObject



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/view.rb', line 319

def render(*args)
  if args.first.is_a?(Hash)
    initialization_options = args.shift
    content_method = initialization_options[:method]
  else
    content_method = args.shift
    initialization_options = args.shift || {}
  end
  
  content_method ||= self.class.default_content_method
  self.render_style = initialization_options[:style] || self.class.default_render_style
  
  self.output = "" if curated?
  
  if block
    send(content_method, &block)
  else
    send(content_method)
  end
  
  render_buffer
  output
end

#xml(opts = {}) ⇒ Object



183
184
185
186
# File 'lib/view.rb', line 183

def xml(opts={})
  opts = {:version => 1.0, :encoding => 'utf-8'}.merge(opts)
  add_to_buffer Xml.new(parse_tag_arguments(:xml, [opts]))
end