Class: Compony::RequestContext

Inherits:
Dslblend::Base
  • Object
show all
Defined in:
lib/compony/request_context.rb

Overview

This encapsulates useful methods for accessing data within a request.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(component, controller, *additional_providers, helpers: nil, locals: {}) ⇒ RequestContext

Returns a new instance of RequestContext.



10
11
12
13
14
15
16
17
18
# File 'lib/compony/request_context.rb', line 10

def initialize(component, controller, *additional_providers, helpers: nil, locals: {})
  # DSL provider is this class, controller is an additional provider, main provider should be the component
  # Note: we have to manually set the main provider here as the auto-detection sets it to the VerbDsl instance around the block,
  #       leading to undesired caching effects (e.g. components being re-used, even if the comp_opts have changed)
  @controller = controller
  @helpers = helpers || controller.helpers
  @local_assigns = locals.with_indifferent_access
  super(@helpers, @controller, *additional_providers, main_provider: component)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, **kwargs) ⇒ Object

Provide access to local assigns as if it were a Rails context



35
36
37
38
# File 'lib/compony/request_context.rb', line 35

def method_missing(method, *args, **kwargs, &)
  return @local_assigns[method] if @local_assigns.key?(method)
  return super
end

Instance Attribute Details

#controllerObject (readonly)

Allow explicit access to the controller object. All controller methods are delgated.



6
7
8
# File 'lib/compony/request_context.rb', line 6

def controller
  @controller
end

#helpersObject (readonly)



7
8
9
# File 'lib/compony/request_context.rb', line 7

def helpers
  @helpers
end

#local_assignsObject (readonly)



8
9
10
# File 'lib/compony/request_context.rb', line 8

def local_assigns
  @local_assigns
end

Instance Method Details

#componentObject



24
25
26
# File 'lib/compony/request_context.rb', line 24

def component
  @_main_provider
end

#content(name) ⇒ Object

Renders a content block from the current component. Does nothing if no such content block exists.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/compony/request_context.rb', line 51

def content(name) # rubocop:disable Naming/PredicateMethod
  name = name.to_sym
  content_block = component.content_blocks.find { |el| el.name == name }
  return false if content_block.nil?

  # We have to clear Rails' output_buffer to prevent double rendering of blocks. To achieve this, a fresh render context is instanciated.
  concat controller.render_to_string(
    type:   :dyny,
    locals: { render_component: component, render_controller: controller, render_locals: local_assigns, render_block: content_block },
    inline: <<~RUBY
      Compony::RequestContext.new(render_component, render_controller, helpers: self, locals: local_assigns).evaluate_with_backfire(&render_block.payload)
    RUBY
  )
  return true
end

#content!(name) ⇒ Object

Like #content, but fails if no such content block exists.

See Also:



69
70
71
# File 'lib/compony/request_context.rb', line 69

def content!(name)
  content(name) || fail("Content block #{name.inspect} not found in #{component.inspect}.")
end

#evaluate_with_backfireObject



20
21
22
# File 'lib/compony/request_context.rb', line 20

def evaluate_with_backfire(&)
  evaluate(backfire_vars: true, &)
end

#render_intentObject

View helper that renders an intent through the default button class. All non-mentioned parameters are given to the intent initializer. When inside a request context (content do...), this precedes ViewHelpers#render_intent.



76
77
78
# File 'lib/compony/request_context.rb', line 76

def render_intent(*, **)
  Compony.intent(*, **).render(controller, component)
end

#render_sub_comp(turbo_frame: nil) ⇒ Object

View helper that instanciates a sub comp and renders it. Example usage: concat render_sub_comp(:list, @data.belongings) If the parameter turbo_frame is given, the sub comp is rendered inside a hotwire turbo frame. This is useful when having forms in multiple nested comps.



83
84
85
86
87
88
89
90
91
# File 'lib/compony/request_context.rb', line 83

def render_sub_comp(*, turbo_frame: nil, **)
  if turbo_frame
    turbo_frame_tag(turbo_frame.to_sym) do
      concat sub_comp(*, **).render(controller)
    end
  else
    sub_comp(*, **).render(controller)
  end
end

#request_contextObject

Explicit accessor to this object. As Dslblend hides where a method comes from, this makes code modifying the request context more explicit. This is for instance useful when a component wishes to extend the request context with a module in order to define methods directly on the context.



30
31
32
# File 'lib/compony/request_context.rb', line 30

def request_context
  self
end

#respond_to_missing?(method, include_all) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
43
# File 'lib/compony/request_context.rb', line 40

def respond_to_missing?(method, include_all)
  return true if @local_assigns.key?(method)
  return super
end