Class: Flutterby::View

Inherits:
Object
  • Object
show all
Includes:
ERB::Util
Defined in:
lib/flutterby/view.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node, opts = {}) ⇒ View

Returns a new instance of View.



16
17
18
19
20
21
# File 'lib/flutterby/view.rb', line 16

def initialize(node, opts = {})
  @node = node
  @opts = opts
  @source = node.source
  @_body = nil
end

Instance Attribute Details

#_bodyObject

Returns the value of attribute _body.



6
7
8
# File 'lib/flutterby/view.rb', line 6

def _body
  @_body
end

#nodeObject (readonly) Also known as: page

Returns the value of attribute node.



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

def node
  @node
end

#optsObject (readonly)

Returns the value of attribute opts.



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

def opts
  @opts
end

#sourceObject (readonly)

Returns the value of attribute source.



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

def source
  @source
end

Class Method Details

.for(node, *args) ⇒ Object

Factory method that returns a newly created view for the given node. It also makes sure all available _view.rb extensions are loaded.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/flutterby/view.rb', line 128

def for(node, *args)
  # create a new view instance
  view = new(node, *args)

  # walk the tree up to dynamically extend the view
  TreeWalker.walk_down(node) do |e|
    if view_node = e.sibling("_view.rb")
      case view_node.ext
      when "rb" then
        view.instance_eval(view_node.source)
      else
        raise "Unknown view extension #{view_node.full_name}"
      end
    end
  end

  # return the finished view object
  view
end

Instance Method Details

#apply_layout!(input) ⇒ Object



47
48
49
50
51
52
53
54
55
56
# File 'lib/flutterby/view.rb', line 47

def apply_layout!(input)
  TreeWalker.walk_up(node, input) do |node, current|
    if layout = node.sibling("_layout")
      tilt = Flutterby::Filters.tilt(layout.ext, layout.source)
      tilt.render(self) { current }.html_safe
    else
      current
    end
  end
end

#date_format(date, fmt) ⇒ Object



62
63
64
# File 'lib/flutterby/view.rb', line 62

def date_format(date, fmt)
  date.strftime(fmt)
end

#debug(obj) ⇒ Object



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

def debug(obj)
  tag(:pre, class: "debug") { h obj.to_yaml }
end

#extend_view(*mods, &blk) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/flutterby/view.rb', line 112

def extend_view(*mods, &blk)
  if block_given?
    mods << Module.new(&blk)
  end

  extend(*mods)
end

#find(*args) ⇒ Object



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

def find(*args)
  node.find(*args) or raise "No node found for #{args}"
end


99
100
101
102
103
104
105
106
# File 'lib/flutterby/view.rb', line 99

def link_to(text, target, attrs = {})
  href = case target
  when Flutterby::Node then target.url
  else target.to_s
  end

  tag(:a, attrs.merge(href: href)) { text }
end

#loggerObject



120
121
122
# File 'lib/flutterby/view.rb', line 120

def logger
  @logger ||= Flutterby.logger
end

#raw(str) ⇒ Object



66
67
68
# File 'lib/flutterby/view.rb', line 66

def raw(str)
  str.html_safe
end

#render(expr, *args) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/flutterby/view.rb', line 70

def render(expr, *args)
  if expr.is_a?(Node)
    expr.render(*args)
  else
    find(expr).render(*args)
  end
end

#render!Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/flutterby/view.rb', line 23

def render!
  time = Benchmark.realtime do
    Filters.apply!(self)

    # Apply layouts
    if opts[:layout] && node.page?
      @_body = apply_layout!(@_body)
    end
  end

  # Log rendering times using different colors based on duration
  color = if time > 1
    :red
  elsif time > 0.25
    :yellow
  else
    :green
  end

  logger.debug "Rendered #{node.url.colorize(:blue)} in #{sprintf("%.1fms", time * 1000).colorize(color)}"

  @_body
end

#siblings(*args) ⇒ Object



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

def siblings(*args)
  node.siblings(*args)
end

#tag(name, attributes = {}) ⇒ Object



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

def tag(name, attributes = {})
  ActiveSupport::SafeBuffer.new.tap do |output|
    attributes_str = attributes.keys.sort.map do |k|
      %{#{h k}="#{h attributes[k]}"}
    end.join(" ")

    opening_tag = "#{h name.downcase} #{attributes_str}".strip
    output << "<#{opening_tag}>".html_safe
    output << yield if block_given?
    output << "</#{h name}>".html_safe
  end
end

#to_sObject



58
59
60
# File 'lib/flutterby/view.rb', line 58

def to_s
  @_body ||= render!
end