view_component_reflex 3.1.5 → 3.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63a22f733ad6878a7014b1b22ea8de86df54d0f1a7be763f7436998970ea8823
4
- data.tar.gz: e2c6b8ef91bf34ed84a974a8a4e2380c589c8d06dbf85475850390bf7966c599
3
+ metadata.gz: 16b2b912f26f5a3ac4cb26e659d443ce52bca8458154e4cc464ea29d484e9501
4
+ data.tar.gz: 5b320e62171c3ab7e436f39db45c98c52f7274b8f477a6f9ee11af13ac2b1899
5
5
  SHA512:
6
- metadata.gz: 9c231c61349cf8e823f361bd9c2efa768028b2d2c2b794d6f540306068dee0d37fa9d4c72a4e8e8bd6733156f625e320c445dbcd47a6725184755776072612e9
7
- data.tar.gz: 4c5c3727f07b6d9c997386468a13a1c9474e83feb66b0545f27389c9c22e36bac4b33b18b62147e3504fc8f862d60cd35eee36ba1f543d9ad2dcb779be39a502
6
+ metadata.gz: 22d9b03168e43de149a861420b8b819be452ffeb474b8b700cc74af37115cc98849284f2723c920408db60acc957121bf519a1430f65b4efeda503494ccd511f
7
+ data.tar.gz: b0dee0a65bdcf956cebaac0220c615f8fcdbd15d3ecbdeb147129a76612a00556813940416da1938d2f2f4c686898855e8bc5c861eda3441e5fddd4442fe6d17
@@ -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,10 +201,23 @@ 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
 
209
+ def content
210
+ if cached_content && !@_render_in_block
211
+ cached_content
212
+ else
213
+ super
214
+ end
215
+ end
216
+
217
+ def cached_content
218
+ @__cached_content__
219
+ end
220
+
192
221
  def create_safe_state
193
222
  new_state = {}
194
223
 
@@ -196,6 +225,9 @@ module ViewComponentReflex
196
225
  safe_instance_variables.each do |k|
197
226
  new_state[k] = instance_variable_get(k)
198
227
  end
228
+
229
+ new_state[:@__cached_content__] = content
230
+
199
231
  new_state
200
232
  end
201
233
 
@@ -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
 
@@ -13,9 +20,8 @@ module ViewComponentReflex
13
20
  end
14
21
  if primary_selector
15
22
  prevent_refresh!
16
-
17
- controller.process(params[:action])
18
- document = Nokogiri::HTML(controller.response.body)
23
+
24
+ document = controller_document
19
25
  [primary_selector, *rest].each do |s|
20
26
  html = document.css(s)
21
27
  if html.present?
@@ -24,14 +30,13 @@ module ViewComponentReflex
24
30
  html: html.inner_html,
25
31
  children_only: true,
26
32
  permanent_attribute_name: "data-reflex-permanent",
27
- stimulus_reflex: stimulus_reflex_data
28
33
  )
29
34
  end
30
35
  end
31
36
  else
32
37
  refresh_component!
33
38
  end
34
- CableReady::Channels.instance.broadcast
39
+ CableReady::Channels.instance[stream].broadcast
35
40
  end
36
41
 
37
42
  def stream
@@ -42,22 +47,35 @@ module ViewComponentReflex
42
47
  @stream = channel
43
48
  end
44
49
 
45
- def refresh_component!
50
+ def component_document
46
51
  component.tap do |k|
47
- k.define_singleton_method(:key) do
48
- element.dataset[:key]
52
+ k.define_singleton_method(:initialize_component) do
53
+ @key = element.dataset[:key]
49
54
  end
50
55
  end
56
+
51
57
  document = Nokogiri::HTML(component.render_in(controller.view_context))
58
+ end
59
+
60
+ def refresh_component!
52
61
  CableReady::Channels.instance[stream].morph(
53
62
  selector: selector,
54
63
  children_only: true,
55
- html: document.css(selector).inner_html,
64
+ html: component_document.css(selector).inner_html,
56
65
  permanent_attribute_name: "data-reflex-permanent",
57
- stimulus_reflex: stimulus_reflex_data
58
66
  )
59
67
  end
60
68
 
69
+ def default_morph
70
+ save_state
71
+ html = if component.can_render_to_string?
72
+ component_document.css(selector).to_html
73
+ else
74
+ controller_document.css(selector).to_html
75
+ end
76
+ morph selector, html
77
+ end
78
+
61
79
  def stimulus_reflex_data
62
80
  {
63
81
  reflex_id: reflex_id,
@@ -96,27 +114,20 @@ module ViewComponentReflex
96
114
  !!name.to_proc
97
115
  end
98
116
 
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
117
  def method_missing(name, *args, &blk)
111
- morph :nothing
112
118
  super unless respond_to_missing?(name)
119
+
113
120
  state.each do |k, v|
114
121
  component.instance_variable_set(k, v)
115
122
  end
116
123
 
117
124
  component.send(name, *args, &blk)
118
125
 
119
- refresh! unless @prevent_refresh
126
+ if @prevent_refresh
127
+ morph :nothing
128
+ else
129
+ default_morph
130
+ end
120
131
  end
121
132
 
122
133
  def prevent_refresh!
@@ -182,11 +193,23 @@ module ViewComponentReflex
182
193
  end
183
194
 
184
195
  def set_state(new_state = {})
185
- ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
196
+ state_adapter.set_state(request, controller, key, new_state)
197
+ end
198
+
199
+ def key
200
+ element.dataset[:key]
201
+ end
202
+
203
+ def state_adapter
204
+ ViewComponentReflex::Engine.state_adapter
186
205
  end
187
206
 
188
207
  def state
189
- ViewComponentReflex::Engine.state_adapter.state(request, element.dataset[:key])
208
+ state_adapter.state(request, key)
209
+ end
210
+
211
+ def initial_state
212
+ state_adapter.state(request, "#{key}_initial")
190
213
  end
191
214
 
192
215
  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.5'
2
+ VERSION = '3.1.10'
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.5
4
+ version: 3.1.10
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-29 00:00:00.000000000 Z
11
+ date: 2021-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: 2.28.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '0'
60
+ version: 2.28.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: sqlite3
63
63
  requirement: !ruby/object:Gem::Requirement