view_component_reflex 3.1.3 → 3.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07c2234a9c3569075c683fba6d62938f203cc647472c092d469533adbf017271
4
- data.tar.gz: 432352a437e6a3bcd4125de57e1c59dba8b852a324a1255d19ebcc1745e280f3
3
+ metadata.gz: 9b88985bd86d0a17dad82c4f01452e0f62a90c6b46984e9df1de0bc7242e1788
4
+ data.tar.gz: da3801c7566583a2325d60cab55f35c5f3bca0a6031419f05279df7d46de2a12
5
5
  SHA512:
6
- metadata.gz: ccf4ee642dafb9e2aa8739dca124df3a2edfbd43bd94ff6cb8186efbc13053a8048ade26451fb64179293505ee1f25d6bab3081c81205560210bdc0a8cd4a362
7
- data.tar.gz: af090c13d376712e06de6b9d0fff96389afec94a2f52224019c6a1ed1d2dc223620731ed0e9ead87bec8dd6238d1feb70069785d435b362b4de71f5285508397
6
+ metadata.gz: 33f8f7db2aac6d2808ad1b88eff827c0d91e8b16606a59c7dc6cab16f1b805f329162167026f0d7698556ac5fbd00b98d0ec8da720c91b0015459218e46da1fb
7
+ data.tar.gz: 5ff2eddfcbfbdf41c7caf47fe7577c737b59dd705affef9e56d0ae3f585c34cff2c5a11d41385c04866c4142f8119f7f7108cb3cf73da19bc3fdca3765f50fd3
@@ -1,6 +1,7 @@
1
1
  module ViewComponentReflex
2
2
  class Component < ViewComponent::Base
3
3
  class_attribute :reflex_base_class, default: ViewComponentReflex::Reflex
4
+ attr_reader :key
4
5
 
5
6
  class << self
6
7
  def init_stimulus_reflex
@@ -55,7 +56,7 @@ module ViewComponentReflex
55
56
  end
56
57
 
57
58
  def component_controller(opts_or_tag = :div, opts = {}, &blk)
58
- init_key
59
+ initialize_component
59
60
 
60
61
  tag = :div
61
62
  options = if opts_or_tag.is_a? Hash
@@ -77,11 +78,64 @@ module ViewComponentReflex
77
78
  omitted_from_state.empty?
78
79
  end
79
80
 
80
- # key is required if you're using state
81
- # We can't initialize the session state in the initial method
82
- # because it doesn't have a view_context yet
83
- # This is the next best place to do it
84
- def init_key
81
+ # We can't truly initialize the component without the view_context,
82
+ # which isn't available in the `initialize` method. We require the
83
+ # developer to wrap components in `component_controller`, so this is where
84
+ # we truly initialize the component.
85
+ # This method is overridden in reflex.rb when the component is re-rendered. The
86
+ # override simply sets @key to element.dataset[:key]
87
+ # We don't want it to initialize the state again, and since we're rendering the component
88
+ # outside of the view, we need to skip the initialize_key method as well
89
+ def initialize_component
90
+ initialize_key
91
+ initialize_state
92
+ end
93
+
94
+ # Note to self:
95
+ # This has to be in the Component class because there are situations
96
+ # where the controller is the one rendering the component
97
+ # so we can't rely on the component created by the reflex
98
+ def initialize_state
99
+ return if state_initialized?
100
+ adapter = ViewComponentReflex::Engine.state_adapter
101
+
102
+ # newly mounted
103
+ if !stimulus_reflex? || adapter.state(request, @key).empty?
104
+
105
+ new_state = create_safe_state
106
+
107
+ adapter.wrap_write_async do
108
+ adapter.store_state(request, @key, new_state)
109
+ adapter.store_state(request, "#{@key}_initial", new_state)
110
+ end
111
+
112
+ # updating a mounted component
113
+ else
114
+ initial_state = adapter.state(request, "#{@key}_initial")
115
+
116
+ parameters_changed = []
117
+ adapter.state(request, @key).each do |k, v|
118
+ instance_value = instance_variable_get(k)
119
+ if permit_parameter?(initial_state[k], instance_value)
120
+ parameters_changed << k
121
+ adapter.wrap_write_async do
122
+ adapter.set_state(request, controller, "#{@key}_initial", {k => instance_value})
123
+ adapter.set_state(request, controller, @key, {k => instance_value})
124
+ end
125
+ else
126
+ instance_variable_set(k, v)
127
+ end
128
+ end
129
+ after_state_initialized(parameters_changed)
130
+ end
131
+ @state_initialized = true
132
+ end
133
+
134
+ def state_initialized?
135
+ @state_initialized
136
+ end
137
+
138
+ def initialize_key
85
139
  # we want the erb file that renders the component. `caller` gives the file name,
86
140
  # and line number, which should be unique. We hash it to make it a nice number
87
141
  erb_file = caller.select { |p| p.match? /.\.html\.(haml|erb|slim)/ }[1]
@@ -137,44 +191,6 @@ module ViewComponentReflex
137
191
  # # no op
138
192
  # end
139
193
 
140
- def key
141
- adapter = ViewComponentReflex::Engine.state_adapter
142
-
143
- # initialize session state
144
- if (!stimulus_reflex? || adapter.state(request, @key).empty?) && !@initialized_state
145
-
146
- new_state = create_safe_state
147
-
148
- adapter.wrap_write_async do
149
- adapter.store_state(request, @key, new_state)
150
- adapter.store_state(request, "#{@key}_initial", new_state)
151
- end
152
- elsif !@initialized_state
153
- initial_state = adapter.state(request, "#{@key}_initial")
154
-
155
- # incoming_params = safe_instance_variables.each_with_object({}) { |var, obj| obj[var] = instance_variable_get(var) }
156
- # receive_params(ViewComponentReflex::Engine.state_adapter.state(request, @key), incoming_params)
157
-
158
- parameters_changed = []
159
- adapter.state(request, @key).each do |k, v|
160
- instance_value = instance_variable_get(k)
161
- if permit_parameter?(initial_state[k], instance_value)
162
- parameters_changed << k
163
- adapter.wrap_write_async do
164
- adapter.set_state(request, controller, "#{@key}_initial", {k => instance_value})
165
- adapter.set_state(request, controller, @key, {k => instance_value})
166
- end
167
- else
168
- instance_variable_set(k, v)
169
- end
170
- end
171
- after_state_initialized(parameters_changed)
172
- end
173
-
174
- @initialized_state = true
175
- @key
176
- end
177
-
178
194
  def safe_instance_variables
179
195
  instance_variables - unsafe_instance_variables - omitted_from_state
180
196
  end
@@ -185,7 +201,8 @@ module ViewComponentReflex
185
201
  [
186
202
  :@view_context, :@lookup_context, :@view_renderer, :@view_flow,
187
203
  :@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
188
- :@helpers, :@controller, :@request, :@tag_builder, :@initialized_state
204
+ :@helpers, :@controller, :@request, :@tag_builder, :@state_initialized,
205
+ :@_content_evaluated, :@_render_in_block
189
206
  ]
190
207
  end
191
208
 
@@ -196,6 +213,7 @@ module ViewComponentReflex
196
213
  safe_instance_variables.each do |k|
197
214
  new_state[k] = instance_variable_get(k)
198
215
  end
216
+
199
217
  new_state
200
218
  end
201
219
 
@@ -5,6 +5,13 @@ module ViewComponentReflex
5
5
  attr_accessor :component_class
6
6
  end
7
7
 
8
+ # pretty sure I can't memoize this because we need
9
+ # to re-render every time
10
+ def controller_document
11
+ controller.process(params[:action])
12
+ Nokogiri::HTML(controller.response.body)
13
+ end
14
+
8
15
  def refresh!(primary_selector = nil, *rest)
9
16
  save_state
10
17
 
@@ -14,24 +21,21 @@ module ViewComponentReflex
14
21
  if primary_selector
15
22
  prevent_refresh!
16
23
 
17
- controller.process(params[:action])
18
- document = Nokogiri::HTML(controller.response.body)
19
24
  [primary_selector, *rest].each do |s|
20
- html = document.css(s)
25
+ html = controller_document.css(s)
21
26
  if html.present?
22
27
  CableReady::Channels.instance[stream].morph(
23
28
  selector: s,
24
29
  html: html.inner_html,
25
30
  children_only: true,
26
31
  permanent_attribute_name: "data-reflex-permanent",
27
- stimulus_reflex: stimulus_reflex_data
28
32
  )
29
33
  end
30
34
  end
31
35
  else
32
36
  refresh_component!
33
37
  end
34
- CableReady::Channels.instance.broadcast
38
+ CableReady::Channels.instance[stream].broadcast
35
39
  end
36
40
 
37
41
  def stream
@@ -42,28 +46,41 @@ module ViewComponentReflex
42
46
  @stream = channel
43
47
  end
44
48
 
45
- def refresh_component!
49
+ def component_document
46
50
  component.tap do |k|
47
- k.define_singleton_method(:key) do
48
- element.dataset[:key]
51
+ k.define_singleton_method(:initialize_component) do
52
+ @key = element.dataset[:key]
49
53
  end
50
54
  end
55
+
51
56
  document = Nokogiri::HTML(component.render_in(controller.view_context))
57
+ end
58
+
59
+ def refresh_component!
52
60
  CableReady::Channels.instance[stream].morph(
53
61
  selector: selector,
54
62
  children_only: true,
55
- html: document.css(selector).inner_html,
63
+ html: component_document.css(selector).inner_html,
56
64
  permanent_attribute_name: "data-reflex-permanent",
57
- stimulus_reflex: stimulus_reflex_data
58
65
  )
59
66
  end
60
67
 
68
+ def default_morph
69
+ save_state
70
+ html = if component.can_render_to_string?
71
+ component_document.css(selector).to_html
72
+ else
73
+ controller_document.css(selector).to_html
74
+ end
75
+ morph selector, html
76
+ end
77
+
61
78
  def stimulus_reflex_data
62
79
  {
63
80
  reflex_id: reflex_id,
64
- xpath: xpath,
81
+ xpath_controller: xpath_controller,
82
+ xpath_element: xpath_element,
65
83
  target: target,
66
- c_xpath: c_xpath,
67
84
  reflex_controller: reflex_controller,
68
85
  url: url,
69
86
  morph: :page,
@@ -96,25 +113,20 @@ module ViewComponentReflex
96
113
  !!name.to_proc
97
114
  end
98
115
 
99
- # this is copied out of stimulus_reflex/reflex.rb and modified
100
- def morph(selectors, html = "")
101
- case selectors
102
- when :nothing
103
- @broadcaster = StimulusReflex::NothingBroadcaster.new(self)
104
- else
105
- @broadcaster = StimulusReflex::SelectorBroadcaster.new(self) unless broadcaster.selector?
106
- broadcaster.morphs << [selectors, html]
107
- end
108
- end
109
-
110
- def method_missing(name, *args)
111
- morph :nothing
116
+ def method_missing(name, *args, &blk)
112
117
  super unless respond_to_missing?(name)
118
+
113
119
  state.each do |k, v|
114
120
  component.instance_variable_set(k, v)
115
121
  end
116
- name.to_proc.call(component, *args)
117
- refresh! unless @prevent_refresh
122
+
123
+ component.send(name, *args, &blk)
124
+
125
+ if @prevent_refresh
126
+ morph :nothing
127
+ else
128
+ default_morph
129
+ end
118
130
  end
119
131
 
120
132
  def prevent_refresh!
@@ -180,11 +192,23 @@ module ViewComponentReflex
180
192
  end
181
193
 
182
194
  def set_state(new_state = {})
183
- ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
195
+ state_adapter.set_state(request, controller, key, new_state)
196
+ end
197
+
198
+ def key
199
+ element.dataset[:key]
200
+ end
201
+
202
+ def state_adapter
203
+ ViewComponentReflex::Engine.state_adapter
184
204
  end
185
205
 
186
206
  def state
187
- ViewComponentReflex::Engine.state_adapter.state(request, element.dataset[:key])
207
+ state_adapter.state(request, key)
208
+ end
209
+
210
+ def initial_state
211
+ state_adapter.state(request, "#{key}_initial")
188
212
  end
189
213
 
190
214
  def save_state
@@ -9,6 +9,7 @@ module ViewComponentReflex
9
9
  new_state.each do |k, v|
10
10
  state(request, key)[k] = v
11
11
  end
12
+ p new_state
12
13
  store = request.session.instance_variable_get("@by")
13
14
  store.commit_session request, controller.response
14
15
  end
@@ -18,6 +19,7 @@ module ViewComponentReflex
18
19
  new_state.each do |k, v|
19
20
  request.session[key][k] = v
20
21
  end
22
+ p new_state
21
23
  end
22
24
 
23
25
  def self.wrap_write_async
@@ -1,3 +1,3 @@
1
1
  module ViewComponentReflex
2
- VERSION = '3.1.3'
2
+ VERSION = '3.1.8'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: view_component_reflex
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.3
4
+ version: 3.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua LeBlanc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-14 00:00:00.000000000 Z
11
+ date: 2021-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 3.4.0
39
+ version: 3.4.1
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 3.4.0
46
+ version: 3.4.1
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: view_component
49
49
  requirement: !ruby/object:Gem::Requirement