Class: ViewComponentReflex::Reflex

Inherits:
StimulusReflex::Reflex
  • Object
show all
Defined in:
lib/view_component_reflex/reflex.rb

Class Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &blk) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/view_component_reflex/reflex.rb', line 126

def method_missing(name, *args, &blk)
  super unless respond_to_missing?(name)

  state.each do |k, v|
    component.instance_variable_set(k, v)
  end

  component.send(name, *args, &blk)

  if @prevent_refresh
    morph :nothing
  else
    default_morph
  end
end

Class Attribute Details

.component_classObject

Returns the value of attribute component_class.



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

def component_class
  @component_class
end

Instance Method Details

#cable_readyObject



14
15
16
# File 'lib/view_component_reflex/reflex.rb', line 14

def cable_ready
  CableReady::Channels.instance[stream]
end

#component_documentObject



62
63
64
# File 'lib/view_component_reflex/reflex.rb', line 62

def component_document
  Nokogiri::HTML(component.render_in(controller.view_context))
end

#controller_documentObject

pretty sure I can’t memoize this because we need to re-render every time



9
10
11
12
# File 'lib/view_component_reflex/reflex.rb', line 9

def controller_document
  controller.process(params[:action])
  Nokogiri::HTML(controller.response.body)
end

#default_morphObject



76
77
78
79
80
81
82
83
84
# File 'lib/view_component_reflex/reflex.rb', line 76

def default_morph
  save_state
  html = if component.can_render_to_string?
    component_document.css(selector).to_html
  else
    controller_document.css(selector).to_html
  end
  morph selector, html
end

#inject_key_into_componentObject



54
55
56
57
58
59
60
# File 'lib/view_component_reflex/reflex.rb', line 54

def inject_key_into_component
  component.tap do |k|
    k.define_singleton_method(:initialize_component) do
      @key = element.dataset[:key]
    end
  end
end

#method(name) ⇒ Object

SR’s delegate_call_to_reflex in channel.rb uses method to gather the method parameters, but since we’re abusing method_missing here, that’ll always fail



117
118
119
120
# File 'lib/view_component_reflex/reflex.rb', line 117

def method(name)
  component.adapter.extend_reflex(self)
  component.method(name.to_sym)
end

#prevent_refresh!Object



142
143
144
# File 'lib/view_component_reflex/reflex.rb', line 142

def prevent_refresh!
  @prevent_refresh = true
end

#refresh!(primary_selector = nil, *rest) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/view_component_reflex/reflex.rb', line 18

def refresh!(primary_selector = nil, *rest)
  save_state

  if primary_selector.nil? && !component.can_render_to_string?
    primary_selector = selector
  end
  if primary_selector
    prevent_refresh!
    
    document = controller_document
    [primary_selector, *rest].each do |s|
      html = document.css(s)
      if html.present?
        cable_ready.morph(
          selector: s,
          html: html.inner_html,
          children_only: true,
          permanent_attribute_name: "data-reflex-permanent",
          reflex_id: reflex_id
        )
      end
    end
  else
    refresh_component!
  end
  cable_ready.broadcast
end

#refresh_all!Object



106
107
108
# File 'lib/view_component_reflex/reflex.rb', line 106

def refresh_all!
  refresh!("body")
end

#refresh_component!Object



66
67
68
69
70
71
72
73
74
# File 'lib/view_component_reflex/reflex.rb', line 66

def refresh_component!
  cable_ready.morph(
    selector: selector,
    children_only: true,
    html: component_document.css(selector).to_html,
    permanent_attribute_name: "data-reflex-permanent",
    reflex_id: reflex_id
  )
end

#respond_to_missing?(name, _ = false) ⇒ Boolean

Returns:

  • (Boolean)


122
123
124
# File 'lib/view_component_reflex/reflex.rb', line 122

def respond_to_missing?(name, _ = false)
  !!name.to_proc
end

#selectorObject



110
111
112
# File 'lib/view_component_reflex/reflex.rb', line 110

def selector
  "[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]"
end

#stimulus_reflex_dataObject



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/view_component_reflex/reflex.rb', line 86

def stimulus_reflex_data
  {
    reflex_id: reflex_id,
    xpath_controller: xpath_controller,
    xpath_element: xpath_element,
    target: target,
    reflex_controller: reflex_controller,
    version: version,
    url: url,
    morph: :page,
    attrs: {
      key: element.dataset[:key]
    }
  }
end

#streamObject



46
47
48
# File 'lib/view_component_reflex/reflex.rb', line 46

def stream
  @stream ||= stream_name
end

#stream_to(channel) ⇒ Object



50
51
52
# File 'lib/view_component_reflex/reflex.rb', line 50

def stream_to(channel)
  @stream = channel
end

#targetObject



102
103
104
# File 'lib/view_component_reflex/reflex.rb', line 102

def target
  "#{component_class}##{method_name}"
end