view_component_reflex 1.6.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -2
- data/app/components/view_component_reflex/component.rb +74 -29
- data/lib/view_component_reflex.rb +8 -7
- data/lib/view_component_reflex/engine.rb +13 -13
- data/lib/view_component_reflex/state_adapter/memory.rb +25 -0
- data/lib/view_component_reflex/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb949fc8de60d18d54d72195cd04947ba24ef73db4091b2ddd0c2992287df7d0
|
4
|
+
data.tar.gz: c474384a6b9c073ba4efbf924067113971e67c4e8bdc0fbfa6462471ecf95b6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0f4a365d380e55ba8deb5f567f35fa81b2aa8ab108cd2aca4f6e97041139e8e53f446f30db3ddcea0ee0fcb08e62b2f98feef14b83f5810c54ce705a6564716
|
7
|
+
data.tar.gz: df46044a3c7bddc9ab204ddb052fce04f0cecf190428043a3aa4ff2fb5a1b86d7d4e9524fa509ecbea51991641f8b4da9b8eaed2b1f4ede565c6cdb922a07724
|
data/README.md
CHANGED
@@ -70,8 +70,8 @@ end
|
|
70
70
|
```
|
71
71
|
|
72
72
|
### omitted_from_state
|
73
|
-
Return an array of instance variables you want to omit from state.
|
74
|
-
|
73
|
+
Return an array of instance variables you want to omit from state. Only really useful if you're using the session state
|
74
|
+
adapter, and you have an instance variable that can't be serialized.
|
75
75
|
|
76
76
|
```ruby
|
77
77
|
def omitted_from_state
|
@@ -181,6 +181,11 @@ end
|
|
181
181
|
<% end
|
182
182
|
```
|
183
183
|
|
184
|
+
## State
|
185
|
+
|
186
|
+
By default, view_component_reflex stores component state in memory. You can optionally set the state adapter
|
187
|
+
to use the session by changing `config.state_adapter` to `ViewComponentReflex::StateAdapter::Session`
|
188
|
+
|
184
189
|
## Custom State Adapters
|
185
190
|
|
186
191
|
ViewComponentReflex uses session for its state by default. To change this, add
|
@@ -4,21 +4,53 @@ module ViewComponentReflex
|
|
4
4
|
def init_stimulus_reflex
|
5
5
|
klass = self
|
6
6
|
@stimulus_reflex ||= Object.const_set(name + "Reflex", Class.new(StimulusReflex::Reflex) {
|
7
|
-
def refresh!(
|
7
|
+
def refresh!(*selectors)
|
8
8
|
save_state
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
|
10
|
+
# If the component has instance variables omitted from state,
|
11
|
+
# we can't render it to string from here because those instance
|
12
|
+
# variables will be missing. In that case, set the selectors to the
|
13
|
+
# default selector and manually morph the page
|
14
|
+
if selectors.empty? && !component.can_render_to_string?
|
15
|
+
selectors.push selector
|
16
|
+
end
|
17
|
+
|
18
|
+
# If we're just updating the component itself, we can
|
19
|
+
# directly render it instead of rendering the entire page again
|
20
|
+
if selectors.empty?
|
21
|
+
refresh_component!
|
22
|
+
else
|
23
|
+
@channel.send :render_page_and_broadcast_morph, self, selectors, {
|
24
|
+
"dataset" => element.dataset.to_h,
|
25
|
+
"args" => [],
|
26
|
+
"attrs" => element.attributes.to_h,
|
27
|
+
"selectors" => ["body"],
|
28
|
+
"target" => "#{self.class.name}##{method_name}",
|
29
|
+
"url" => request.url,
|
30
|
+
"permanent_attribute_name" => permanent_attribute_name
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def refresh_component!
|
36
|
+
# The component can't figure out the key when we render from here
|
37
|
+
# Luckily we already know the key, so we can manually override it
|
38
|
+
component.tap do |k|
|
39
|
+
k.define_singleton_method(:key) do
|
40
|
+
element.dataset[:key]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
html = controller.render_component_to_string(component)
|
44
|
+
document = Nokogiri::HTML(html)
|
45
|
+
morph selector, document.css("#{selector} > *").to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
def selector
|
49
|
+
"[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]"
|
18
50
|
end
|
19
51
|
|
20
52
|
def refresh_all!
|
21
|
-
|
53
|
+
morph :body, render_page(self)
|
22
54
|
end
|
23
55
|
|
24
56
|
# SR's delegate_call_to_reflex in channel.rb
|
@@ -32,11 +64,6 @@ module ViewComponentReflex
|
|
32
64
|
!!name.to_proc
|
33
65
|
end
|
34
66
|
|
35
|
-
before_reflex do |a|
|
36
|
-
a.send a.method_name
|
37
|
-
throw :abort
|
38
|
-
end
|
39
|
-
|
40
67
|
def method_missing(name, *args)
|
41
68
|
super unless respond_to_missing?(name)
|
42
69
|
state.each do |k, v|
|
@@ -85,7 +112,7 @@ module ViewComponentReflex
|
|
85
112
|
|
86
113
|
def save_state
|
87
114
|
new_state = {}
|
88
|
-
component.
|
115
|
+
component.safe_instance_variables.each do |k|
|
89
116
|
new_state[k] = component.instance_variable_get(k)
|
90
117
|
end
|
91
118
|
set_state(new_state)
|
@@ -102,6 +129,10 @@ module ViewComponentReflex
|
|
102
129
|
helpers.controller.instance_variable_get(:@stimulus_reflex)
|
103
130
|
end
|
104
131
|
|
132
|
+
def can_render_to_string?
|
133
|
+
omitted_from_state.empty?
|
134
|
+
end
|
135
|
+
|
105
136
|
def component_controller(opts_or_tag = :div, opts = {}, &blk)
|
106
137
|
self.class.init_stimulus_reflex
|
107
138
|
init_key
|
@@ -165,18 +196,10 @@ module ViewComponentReflex
|
|
165
196
|
|
166
197
|
def key
|
167
198
|
# initialize session state
|
168
|
-
if !stimulus_reflex? ||
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
blacklist = [
|
173
|
-
:@view_context, :@lookup_context, :@view_renderer, :@view_flow,
|
174
|
-
:@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
|
175
|
-
:@helpers, :@controller, :@request, :@content
|
176
|
-
]
|
177
|
-
instance_variables.reject { |k| blacklist.include?(k) }.each do |k|
|
178
|
-
new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
|
179
|
-
end
|
199
|
+
if !stimulus_reflex? || ViewComponentReflex::Engine.state_adapter.state(request, @key).empty?
|
200
|
+
|
201
|
+
new_state = create_safe_state
|
202
|
+
|
180
203
|
ViewComponentReflex::Engine.state_adapter.store_state(request, @key, new_state)
|
181
204
|
ViewComponentReflex::Engine.state_adapter.store_state(request, "#{@key}_initial", new_state)
|
182
205
|
else
|
@@ -190,8 +213,30 @@ module ViewComponentReflex
|
|
190
213
|
@key
|
191
214
|
end
|
192
215
|
|
216
|
+
def safe_instance_variables
|
217
|
+
instance_variables - unsafe_instance_variables
|
218
|
+
end
|
219
|
+
|
193
220
|
private
|
194
221
|
|
222
|
+
def unsafe_instance_variables
|
223
|
+
[
|
224
|
+
:@view_context, :@lookup_context, :@view_renderer, :@view_flow,
|
225
|
+
:@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
|
226
|
+
:@helpers, :@controller, :@request, :@content, :@tag_builder
|
227
|
+
]
|
228
|
+
end
|
229
|
+
|
230
|
+
def create_safe_state
|
231
|
+
new_state = {}
|
232
|
+
|
233
|
+
# this will almost certainly break
|
234
|
+
safe_instance_variables.each do |k|
|
235
|
+
new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
|
236
|
+
end
|
237
|
+
new_state
|
238
|
+
end
|
239
|
+
|
195
240
|
def merge_data_attributes(options, attributes)
|
196
241
|
data = options[:data]
|
197
242
|
if data.nil?
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require "view_component_reflex/state_adapter/session"
|
2
|
-
require "view_component_reflex/
|
3
|
-
require
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
require "view_component_reflex/state_adapter/session"
|
2
|
+
require "view_component_reflex/state_adapter/memory"
|
3
|
+
require "view_component_reflex/engine"
|
4
|
+
require 'stimulus_reflex'
|
5
|
+
|
6
|
+
module ViewComponentReflex
|
7
|
+
# Your code goes here...
|
8
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
module ViewComponentReflex
|
2
|
-
class Engine < ::Rails::Engine
|
3
|
-
class << self
|
4
|
-
mattr_accessor :state_adapter
|
5
|
-
|
6
|
-
self.state_adapter = StateAdapter::
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.configure
|
10
|
-
yield self if block_given?
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
1
|
+
module ViewComponentReflex
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
class << self
|
4
|
+
mattr_accessor :state_adapter
|
5
|
+
|
6
|
+
self.state_adapter = StateAdapter::Memory
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.configure
|
10
|
+
yield self if block_given?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
VIEW_COMPONENT_REFLEX_MEMORY_STATE = {}
|
2
|
+
module ViewComponentReflex
|
3
|
+
module StateAdapter
|
4
|
+
class Memory
|
5
|
+
def self.state(request, key)
|
6
|
+
VIEW_COMPONENT_REFLEX_MEMORY_STATE[request.session.id.to_s] ||= {}
|
7
|
+
VIEW_COMPONENT_REFLEX_MEMORY_STATE[request.session.id.to_s][key] ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.set_state(request, _, key, new_state)
|
11
|
+
new_state.each do |k, v|
|
12
|
+
state(request, key)[k] = v
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.store_state(request, key, new_state = {})
|
17
|
+
VIEW_COMPONENT_REFLEX_MEMORY_STATE[request.session.id.to_s] ||= {}
|
18
|
+
VIEW_COMPONENT_REFLEX_MEMORY_STATE[request.session.id.to_s][key] ||= {}
|
19
|
+
new_state.each do |k, v|
|
20
|
+
VIEW_COMPONENT_REFLEX_MEMORY_STATE[request.session.id.to_s][key][k] = v
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
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: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua LeBlanc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -71,6 +71,7 @@ files:
|
|
71
71
|
- app/components/view_component_reflex/component.rb
|
72
72
|
- lib/view_component_reflex.rb
|
73
73
|
- lib/view_component_reflex/engine.rb
|
74
|
+
- lib/view_component_reflex/state_adapter/memory.rb
|
74
75
|
- lib/view_component_reflex/state_adapter/session.rb
|
75
76
|
- lib/view_component_reflex/version.rb
|
76
77
|
homepage: https://github.com/joshleblanc/view_component_reflex
|