view_component_reflex 3.1.4 → 3.1.9

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: e1c5a6bb6d424caf8b1840123432a3c50262739780a9c653c73d3bb4d7154906
4
- data.tar.gz: 9314ec969dd8c0d31ac5751a40a8fa58cdc1f88fac3139775803b15a6284ae30
3
+ metadata.gz: 8df0782e33267ea91ff1e99610107ee004cdec87947087750227907af88a3674
4
+ data.tar.gz: 5f488b266c6ade0cc81317da9ed0cb3d08cb8680654aef045348b3809997c9f4
5
5
  SHA512:
6
- metadata.gz: f2b2dbeca7e309d7611271a81d39bbda1d62c8d4680c81376ad149818bb6b866e5cf8c2d97c378ed5ca2b31d6e1dc05bd2accacc4e56f6d46463ef24c53f95d1
7
- data.tar.gz: a24726fe210f24efe596f82931b74d99fb60dcd89e7c3ce4d4b71dbc8ca6974018bd92c954b3e6942ca6e5b282e469458be8eeaf2de2f978d856fe654e10c5d4
6
+ metadata.gz: 281166ac7c1e2589d9b97733ad3edca6986720c87b239dd779c55529644bff5f8fad352a46abd43dc53c2e46947525d3517335a0621c8fa6478ad23767ef2b31
7
+ data.tar.gz: dece5fcacf66ee99a5fb539b42bb37cd71904435851ac71e8804b5ed75f0d67b8473b4a7e25e288dfbf81299a9c9f1834c418241b3a3055042136d2308f3f4ff
@@ -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
 
@@ -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,22 +46,35 @@ 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,
@@ -96,27 +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
116
  def method_missing(name, *args, &blk)
111
- morph :nothing
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
122
 
117
123
  component.send(name, *args, &blk)
118
124
 
119
- refresh! unless @prevent_refresh
125
+ if @prevent_refresh
126
+ morph :nothing
127
+ else
128
+ default_morph
129
+ end
120
130
  end
121
131
 
122
132
  def prevent_refresh!
@@ -182,11 +192,23 @@ module ViewComponentReflex
182
192
  end
183
193
 
184
194
  def set_state(new_state = {})
185
- 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
186
204
  end
187
205
 
188
206
  def state
189
- 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")
190
212
  end
191
213
 
192
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.4'
2
+ VERSION = '3.1.9'
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.4
4
+ version: 3.1.9
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-28 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
@@ -36,28 +36,28 @@ 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
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