Class: TurboReflex::Base

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

Overview

TurboReflex base superclass. All TurboReflex classes should inherit from this class.

Reflexes are executed via a before_action in the Rails controller lifecycle. They have access to the following methods and properties.

  • dom_id .….….….….….. The Rails dom_id helper

  • dom_id_selector .….….…. Returns a CSS selector for a dom_id

  • controller .….….….….. The Rails controller processing the HTTP request

  • element .….….….….…. A struct that represents the DOM element that triggered the reflex

  • morph .….….….….…… Appends a Turbo Stream to morph a DOM element

  • params .….….….….….. Reflex specific params (frame_id, element, etc.)

  • render .….….….….….. Renders Rails templates, partials, etc. (doesn’t halt controller request handling)

  • render_response .….….…. Renders a full controller response

  • renderer .….….….….… An ActionController::Renderer

  • turbo_stream .….….….… A Turbo Stream TagBuilder

  • turbo_streams .….….…… A list of Turbo Streams to append to the response (also aliased as streams)

  • state .….….….….…… An object that stores ephemeral ‘state`

They also have access to the following class methods:

  • prevent_controller_action … Prevents the rails controller/action from running (i.e. the reflex handles the response entirely)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(runner) ⇒ Base

Returns a new instance of Base.



82
83
84
85
86
# File 'lib/turbo_reflex/base.rb', line 82

def initialize(runner)
  @runner = runner
  @controller = runner.controller
  @turbo_streams = Set.new
end

Instance Attribute Details

#controllerObject (readonly)

Returns the value of attribute controller.



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

def controller
  @controller
end

#turbo_streamsObject (readonly) Also known as: streams

Returns the value of attribute turbo_streams.



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

def turbo_streams
  @turbo_streams
end

Class Method Details

.prevent_controller_action(options = {}) ⇒ Object



34
35
36
# File 'lib/turbo_reflex/base.rb', line 34

def prevent_controller_action(options = {})
  preventers << options.with_indifferent_access
end

.preventersObject



30
31
32
# File 'lib/turbo_reflex/base.rb', line 30

def preventers
  @preventers ||= Set.new
end

.should_prevent_controller_action?(reflex, method_name) ⇒ Boolean

Returns:

  • (Boolean)


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
# File 'lib/turbo_reflex/base.rb', line 38

def should_prevent_controller_action?(reflex, method_name)
  method_name = method_name.to_s
  match = preventers.find do |options|
    only = options[:only] || []
    only = [only] unless only.is_a?(Array)
    only.map!(&:to_s)

    except = options[:except] || []
    except = [except] unless except.is_a?(Array)
    except.map!(&:to_s)

    options.blank? || only.include?(method_name) || (except.present? && except.exclude?(method_name))
  end

  return false if match.nil?

  if match[:if].present?
    case match[:if]
    when Symbol then reflex.public_send(match[:if])
    when Proc then reflex.instance_exec { match[:if].call reflex }
    end
  elsif match[:unless].present?
    case match[:unless]
    when Symbol then !reflex.public_send(match[:unless])
    when Proc then !(reflex.instance_exec { match[:unless].call(reflex) })
    end
  else
    true
  end
end

Instance Method Details

#dom_id_selectorObject



88
89
90
# File 'lib/turbo_reflex/base.rb', line 88

def dom_id_selector(...)
  "##{dom_id(...)}"
end

#elementObject



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

def element
  @element ||= begin
    attributes = params[:element_attributes]
    OpenStruct.new attributes.merge(
      aria: TurboReflex::AttributeSet.new(:aria, attributes: attributes),
      dataset: TurboReflex::AttributeSet.new(:data, attributes: attributes)
    )
  end
end

#morph(selector, html) ⇒ Object



108
109
110
# File 'lib/turbo_reflex/base.rb', line 108

def morph(selector, html)
  turbo_streams << turbo_stream.invoke("morph", args: [html], selector: selector)
end

#noopObject

default reflex invoked when method not specified



113
114
# File 'lib/turbo_reflex/base.rb', line 113

def noop
end

#paramsObject



116
117
118
# File 'lib/turbo_reflex/base.rb', line 116

def params
  @runner.reflex_params
end

#render(options = {}, locals = {}, &block) ⇒ Object

Same method signature as ActionView::Rendering#render (i.e. controller.view_context.render)



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/turbo_reflex/base.rb', line 93

def render(options = {}, locals = {}, &block)
  return controller.view_context.render(options, locals, &block) unless options.is_a?(Hash)

  options = options.symbolize_keys

  ivars = options[:assigns]&.each_with_object({}) do |(key, value), memo|
    memo[key] = controller.instance_variable_get("@#{key}")
    controller.instance_variable_set "@#{key}", value
  end

  controller.view_context.render(options.except(:assigns), locals, &block)
ensure
  ivars&.each { |key, value| controller.instance_variable_set "@#{key}", value }
end

#should_prevent_controller_action?(method_name) ⇒ Boolean

Returns:

  • (Boolean)


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

def should_prevent_controller_action?(method_name)
  self.class.should_prevent_controller_action? self, method_name
end