Class: Pakyow::Presenter::Renderer

Inherits:
Object
  • Object
show all
Extended by:
Support::ClassState, Support::DeepFreeze
Includes:
Support::Hookable
Defined in:
lib/pakyow/presenter/renderer.rb,
lib/pakyow/presenter/renderer/behavior/setup_forms.rb,
lib/pakyow/presenter/renderer/behavior/place_in_mode.rb,
lib/pakyow/presenter/renderer/behavior/set_page_title.rb,
lib/pakyow/presenter/renderer/behavior/setup_endpoints.rb,
lib/pakyow/presenter/renderer/behavior/render_components.rb,
lib/pakyow/presenter/renderer/behavior/insert_prototype_bar.rb,
lib/pakyow/presenter/renderer/behavior/install_authenticity.rb,
lib/pakyow/presenter/renderer/behavior/create_template_nodes.rb,
lib/pakyow/presenter/renderer/behavior/cleanup_prototype_nodes.rb,
lib/pakyow/presenter/renderer/behavior/cleanup_unbound_bindings.rb

Defined Under Namespace

Modules: Behavior

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app:, presentables:, presenter_class:, composer:, modes: [:default]) ⇒ Renderer

Returns a new instance of Renderer.



35
36
37
38
# File 'lib/pakyow/presenter/renderer.rb', line 35

def initialize(app:, presentables:, presenter_class:, composer:, modes: [:default])
  @app, @presentables, @presenter_class, @composer, @modes = app, presentables, presenter_class, composer, modes
  initialize_presenter
end

Instance Attribute Details

#appObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



33
34
35
# File 'lib/pakyow/presenter/renderer.rb', line 33

def app
  @app
end

#presentablesObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



33
34
35
# File 'lib/pakyow/presenter/renderer.rb', line 33

def presentables
  @presentables
end

#presenterObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



33
34
35
# File 'lib/pakyow/presenter/renderer.rb', line 33

def presenter
  @presenter
end

Class Method Details

.attach!(presenter, app:) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



206
207
208
209
210
211
212
213
214
215
216
# File 'lib/pakyow/presenter/renderer.rb', line 206

def attach!(presenter, app:)
  @__attach_fns.each do |fn|
    options = {}

    if fn.keyword_argument?(:app)
      options[:app] = app
    end

    fn.call(presenter, **options)
  end
end

.build!(view, app:, modes:, composer:) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/pakyow/presenter/renderer.rb', line 185

def build!(view, app:, modes:, composer:)
  @__build_fns.each do |fn|
    options = {}

    if fn.keyword_argument?(:app)
      options[:app] = app
    end

    if fn.keyword_argument?(:modes)
      options[:modes] = modes
    end

    if fn.keyword_argument?(:composer)
      options[:composer] = composer
    end

    fn.call(view, **options)
  end
end

.expose!(connection) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



219
220
221
222
223
# File 'lib/pakyow/presenter/renderer.rb', line 219

def expose!(connection)
  @__expose_fns.each do |fn|
    fn.call(connection)
  end
end

.find_presenter(app, path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/pakyow/presenter/renderer.rb', line 226

def find_presenter(app, path)
  path = String.normalize_path(path)
  unless presenter = @__presenters_by_path[path]
    presenter = if path.nil? || Pakyow.env?(:prototype)
      app.isolated(:Presenter)
    else
      find_presenter_for_path(app, path)
    end

    @__presenters_by_path[path] = presenter
  end

  presenter
end

.render(connection, view_path: nil, presenter_path: nil, modes: [:default]) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/pakyow/presenter/renderer.rb', line 110

def render(connection, view_path: nil, presenter_path: nil, modes: [:default])
  connection.app.__ui_modes.each do |mode, block|
    if block.call(connection)
      modes << mode
    end
  end

  view_path = if view_path
    String.normalize_path(view_path)
  else
    connection.get(:__endpoint_path) || connection.path
  end

  presenter_path = if presenter_path
    String.normalize_path(presenter_path)
  else
    view_path.dup
  end

  if connection.app.is_a?(Plugin) && connection.app.class.mount_path != "/"
    presenter_path.gsub!(/^#{connection.app.class.mount_path}/, "")
  end

  presenter = find_presenter(connection.app, presenter_path)

  expose!(connection)

  renderer = new(
    app: connection.app,
    presentables: connection.values,
    presenter_class: presenter,
    composer: Composers::View.new(view_path, app: connection.app),
    modes: modes
  )

  connection.set_header("content-type", "text/html")

  if connection.app.config.presenter.features.streaming
    connection.stream do
      renderer.perform(connection.body)
    end
  else
    output = renderer.perform(StringIO.new); output.rewind
    connection.body = output
  end

  connection.rendered
end

.render_implicitly(connection) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/pakyow/presenter/renderer.rb', line 160

def render_implicitly(connection)
  view_path = connection.get(:__endpoint_path) || connection.path

  if render_implicitly?(connection)
    begin
      catch :halt do
        render(connection, view_path: view_path)
      end
    rescue UnknownPage => error
      unless connection.app.is_a?(Plugin)
        raise ImplicitRenderingError.build(error, context: view_path)
      end
    end
  end
rescue StandardError => error
  connection.logger.houston(error)

  if connection.app.class.includes_framework?(:routing)
    catch :halt do
      connection.app.controller_for_connection(connection).handle_error(error)
    end
  end
end

Instance Method Details

#marshal_dumpObject



46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/pakyow/presenter/renderer.rb', line 46

def marshal_dump
  {
    app: @app,
    presentables: @presentables.reject { |_, value|
      # Filter out the component connection that we expose for component rendering.
      #
      value.is_a?(@app.isolated(:Connection))
    },
    presenter_class: @presenter_class,
    composer: @composer,
    modes: @modes
  }
end

#marshal_load(state) ⇒ Object



60
61
62
63
# File 'lib/pakyow/presenter/renderer.rb', line 60

def marshal_load(state)
  deserialize(state)
  initialize_presenter
end

#perform(output = String.new) ⇒ Object



40
41
42
43
44
# File 'lib/pakyow/presenter/renderer.rb', line 40

def perform(output = String.new)
  performing :render do
    @presenter.to_html(output)
  end
end