view_component_reflex 1.0.0 → 1.3.0
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30533287ce1445add7dba2ebed5013ed80e792de560fa9c930f3e13dcbd612d7
|
4
|
+
data.tar.gz: bf84f573e602b373855848b2fbe61245967e4f16e7a420b03c1b6414aa1c8c73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47dc5ab24c0711778b07b8460207b1e532c944173d4df2cc8fe33447868b96a9043ad972b5a9672a0ea09ad323199b7cfa15327634199d3218e69e6c797f4196
|
7
|
+
data.tar.gz: d9dbc21f77baf9c73c20352a5163c8af52317a0138393d4128cc34bb60e903227e62e28e0f0e0ad92f4fa10d4206f79d295c74582774b93fefffd14801fe5c44
|
data/README.md
CHANGED
@@ -14,16 +14,16 @@ as any element that stimulates a reflex. ViewComponent is inherently state-less,
|
|
14
14
|
|
15
15
|
### Example
|
16
16
|
```ruby
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
# counter_component.rb
|
18
|
+
class CounterComponent < ViewComponentReflex::Component
|
19
|
+
def initialize
|
20
|
+
@count = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def increment
|
24
|
+
@count += 1
|
25
|
+
end
|
26
|
+
end
|
27
27
|
```
|
28
28
|
|
29
29
|
```erb
|
@@ -34,6 +34,42 @@ as any element that stimulates a reflex. ViewComponent is inherently state-less,
|
|
34
34
|
<% end %>
|
35
35
|
```
|
36
36
|
|
37
|
+
## Collections
|
38
|
+
|
39
|
+
In order to reconcile state to components in collections, you can specify a `collection_key` method that returns some
|
40
|
+
value unique to that component.
|
41
|
+
|
42
|
+
```
|
43
|
+
class TodoComponent < ViewComponentReflex::Component
|
44
|
+
def initialize(todo:)
|
45
|
+
@todo = todo
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection_key
|
49
|
+
@todo.id
|
50
|
+
end
|
51
|
+
end
|
52
|
+
#
|
53
|
+
<%= render(TodoComponent.with_collection(Todo.all)) %>
|
54
|
+
```
|
55
|
+
|
56
|
+
## API
|
57
|
+
|
58
|
+
### permit_parameter?(initial_param, new_params)
|
59
|
+
If a new parameter is passed to the component during rendering, it is used instead of what's in state.
|
60
|
+
If you're storing instances in state, you can use this to properly compare them.
|
61
|
+
|
62
|
+
### omitted_from_state
|
63
|
+
Return an array of instance variables you want to omit from state. Useful if you have an object
|
64
|
+
that isn't serializable as an instance variable, like a form.
|
65
|
+
|
66
|
+
```
|
67
|
+
def omitted_from_state
|
68
|
+
[:@form]
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
|
37
73
|
## Custom State Adapters
|
38
74
|
|
39
75
|
ViewComponentReflex uses session for its state by default. To change this, add
|
@@ -57,13 +93,13 @@ class YourAdapter
|
|
57
93
|
end
|
58
94
|
|
59
95
|
##
|
60
|
-
# set_state is used to modify the state.
|
61
|
-
# access to the request, as well as the controller and other useful objects.
|
96
|
+
# set_state is used to modify the state.
|
62
97
|
#
|
63
|
-
#
|
98
|
+
# request - a rails request object
|
99
|
+
# controller - the current controller
|
64
100
|
# key - a unique string that identifies the component
|
65
101
|
# new_state - the new state to set
|
66
|
-
def self.set_state(
|
102
|
+
def self.set_state(request, controller, key, new_state)
|
67
103
|
# update the state
|
68
104
|
end
|
69
105
|
|
@@ -4,16 +4,16 @@ 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!(primary_selector = "[data-controller
|
7
|
+
def refresh!(primary_selector = "[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]", *selectors)
|
8
8
|
save_state
|
9
9
|
@channel.send :render_page_and_broadcast_morph, self, [primary_selector, *selectors], {
|
10
|
-
dataset
|
11
|
-
args
|
12
|
-
attrs
|
13
|
-
selectors
|
14
|
-
target
|
15
|
-
url
|
16
|
-
|
10
|
+
"dataset" => element.dataset.to_h,
|
11
|
+
"args" => [],
|
12
|
+
"attrs" => element.attributes.to_h,
|
13
|
+
"selectors" => ["body"],
|
14
|
+
"target" => "#{self.class.name}##{method_name}",
|
15
|
+
"url" => request.url,
|
16
|
+
"permanent_attribute_name" => "data-reflex-permanent"
|
17
17
|
}
|
18
18
|
end
|
19
19
|
|
@@ -62,7 +62,7 @@ module ViewComponentReflex
|
|
62
62
|
return @component if @component
|
63
63
|
@component = component_class.allocate
|
64
64
|
reflex = self
|
65
|
-
exposed_methods = [:element, :refresh!, :refresh_all!, :stimulus_controller]
|
65
|
+
exposed_methods = [:params, :request, :element, :refresh!, :refresh_all!, :stimulus_controller, :session]
|
66
66
|
exposed_methods.each do |meth|
|
67
67
|
@component.define_singleton_method(meth) do |*a|
|
68
68
|
reflex.send(meth, *a)
|
@@ -72,7 +72,7 @@ module ViewComponentReflex
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def set_state(new_state = {})
|
75
|
-
ViewComponentReflex::Engine.state_adapter.set_state(
|
75
|
+
ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
|
76
76
|
end
|
77
77
|
|
78
78
|
def state
|
@@ -98,24 +98,42 @@ module ViewComponentReflex
|
|
98
98
|
helpers.controller.instance_variable_get(:@stimulus_reflex)
|
99
99
|
end
|
100
100
|
|
101
|
-
def component_controller(&blk)
|
102
|
-
|
103
|
-
|
101
|
+
def component_controller(opts = {}, &blk)
|
102
|
+
self.class.init_stimulus_reflex
|
103
|
+
init_key
|
104
|
+
opts[:data] = {
|
105
|
+
controller: self.class.stimulus_controller,
|
106
|
+
key: key,
|
107
|
+
**(opts[:data] || {})
|
108
|
+
}
|
109
|
+
content_tag :div, capture(&blk), opts
|
104
110
|
end
|
105
111
|
|
106
112
|
# key is required if you're using state
|
107
113
|
# We can't initialize the session state in the initial method
|
108
114
|
# because it doesn't have a view_context yet
|
109
115
|
# This is the next best place to do it
|
110
|
-
def
|
111
|
-
self.class.init_stimulus_reflex
|
116
|
+
def init_key
|
112
117
|
# we want the erb file that renders the component. `caller` gives the file name,
|
113
118
|
# and line number, which should be unique. We hash it to make it a nice number
|
114
119
|
key = caller.select { |p| p.include? ".html.erb" }[1]&.hash.to_s
|
115
|
-
|
116
|
-
|
117
|
-
|
120
|
+
key += collection_key.to_s if collection_key
|
121
|
+
@key = key
|
122
|
+
end
|
123
|
+
|
124
|
+
def collection_key
|
125
|
+
nil
|
126
|
+
end
|
118
127
|
|
128
|
+
def permit_parameter?(initial_param, new_param)
|
129
|
+
initial_param != new_param
|
130
|
+
end
|
131
|
+
|
132
|
+
def omitted_from_state
|
133
|
+
[]
|
134
|
+
end
|
135
|
+
|
136
|
+
def key
|
119
137
|
# initialize session state
|
120
138
|
if !stimulus_reflex? || session[@key].nil?
|
121
139
|
new_state = {}
|
@@ -124,15 +142,19 @@ module ViewComponentReflex
|
|
124
142
|
blacklist = [
|
125
143
|
:@view_context, :@lookup_context, :@view_renderer, :@view_flow,
|
126
144
|
:@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
|
127
|
-
:@helpers, :@controller, :@request
|
145
|
+
:@helpers, :@controller, :@request, :@content
|
128
146
|
]
|
129
147
|
instance_variables.reject { |k| blacklist.include?(k) }.each do |k|
|
130
|
-
new_state[k] = instance_variable_get(k)
|
148
|
+
new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
|
131
149
|
end
|
132
150
|
ViewComponentReflex::Engine.state_adapter.store_state(request, @key, new_state)
|
151
|
+
ViewComponentReflex::Engine.state_adapter.store_state(request, "#{@key}_initial", new_state)
|
133
152
|
else
|
153
|
+
initial_state = ViewComponentReflex::Engine.state_adapter.state(request, "#{@key}_initial")
|
134
154
|
ViewComponentReflex::Engine.state_adapter.state(request, @key).each do |k, v|
|
135
|
-
|
155
|
+
unless permit_parameter?(initial_state[k], instance_variable_get(k))
|
156
|
+
instance_variable_set(k, v)
|
157
|
+
end
|
136
158
|
end
|
137
159
|
end
|
138
160
|
@key
|
@@ -5,12 +5,12 @@ module ViewComponentReflex
|
|
5
5
|
request.session[key] ||= {}
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.set_state(
|
8
|
+
def self.set_state(request, controller, key, new_state)
|
9
9
|
new_state.each do |k, v|
|
10
|
-
state(
|
10
|
+
state(request, key)[k] = v
|
11
11
|
end
|
12
|
-
store =
|
13
|
-
store.commit_session
|
12
|
+
store = request.session.instance_variable_get("@by")
|
13
|
+
store.commit_session request, controller.response
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.store_state(request, key, new_state = {})
|
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.3.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-06-
|
11
|
+
date: 2020-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|