stimulus_reflex 1.0.1 → 1.0.2
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 +4 -4
- data/Gemfile.lock +97 -18
- data/README.md +47 -11
- data/README.md.orig +159 -0
- data/bin/console +2 -9
- data/bin/standardize +1 -0
- data/lib/stimulus_reflex.rb +9 -3
- data/lib/stimulus_reflex/channel.rb +48 -66
- data/lib/stimulus_reflex/version.rb +1 -1
- metadata +34 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6798571d8f8229083855114f5f499414f308a47e03c438f1b74b5eb534acd78f
|
|
4
|
+
data.tar.gz: 62e2d714b2ae14c16bf4435665d339717d9fa99330d3eb604fa6720c15f64f80
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2d22087e7519727c787770fb971aa510d2480a5b45e00efa78eb708adcc69d89cf085b3fad6544c9a46bb183240ea452ded9ce665495ca7f5d47bcc021c8a7e0
|
|
7
|
+
data.tar.gz: 3b0aaf7d1c98ba7281f24f2d96fb1d043e297847837c2ad38028bac114c7ed7fe80c929e0c58491b646533f8d4958921e8e1483d5bc320c4d04d3034ec2e53aa
|
data/Gemfile.lock
CHANGED
|
@@ -1,67 +1,135 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
stimulus_reflex (1.0.
|
|
5
|
-
|
|
6
|
-
actionpack (>= 5.2.3)
|
|
7
|
-
cable_ready (>= 4.0.1)
|
|
4
|
+
stimulus_reflex (1.0.2)
|
|
5
|
+
cable_ready (>= 4.0.3)
|
|
8
6
|
nokogiri
|
|
9
7
|
rack
|
|
8
|
+
rails (>= 5.2)
|
|
10
9
|
|
|
11
10
|
GEM
|
|
12
11
|
remote: https://rubygems.org/
|
|
13
12
|
specs:
|
|
14
|
-
actioncable (
|
|
15
|
-
actionpack (=
|
|
13
|
+
actioncable (6.0.0)
|
|
14
|
+
actionpack (= 6.0.0)
|
|
16
15
|
nio4r (~> 2.0)
|
|
17
16
|
websocket-driver (>= 0.6.1)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
actionmailbox (6.0.0)
|
|
18
|
+
actionpack (= 6.0.0)
|
|
19
|
+
activejob (= 6.0.0)
|
|
20
|
+
activerecord (= 6.0.0)
|
|
21
|
+
activestorage (= 6.0.0)
|
|
22
|
+
activesupport (= 6.0.0)
|
|
23
|
+
mail (>= 2.7.1)
|
|
24
|
+
actionmailer (6.0.0)
|
|
25
|
+
actionpack (= 6.0.0)
|
|
26
|
+
actionview (= 6.0.0)
|
|
27
|
+
activejob (= 6.0.0)
|
|
28
|
+
mail (~> 2.5, >= 2.5.4)
|
|
29
|
+
rails-dom-testing (~> 2.0)
|
|
30
|
+
actionpack (6.0.0)
|
|
31
|
+
actionview (= 6.0.0)
|
|
32
|
+
activesupport (= 6.0.0)
|
|
21
33
|
rack (~> 2.0)
|
|
22
34
|
rack-test (>= 0.6.3)
|
|
23
35
|
rails-dom-testing (~> 2.0)
|
|
24
|
-
rails-html-sanitizer (~> 1.0, >= 1.0
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
37
|
+
actiontext (6.0.0)
|
|
38
|
+
actionpack (= 6.0.0)
|
|
39
|
+
activerecord (= 6.0.0)
|
|
40
|
+
activestorage (= 6.0.0)
|
|
41
|
+
activesupport (= 6.0.0)
|
|
42
|
+
nokogiri (>= 1.8.5)
|
|
43
|
+
actionview (6.0.0)
|
|
44
|
+
activesupport (= 6.0.0)
|
|
27
45
|
builder (~> 3.1)
|
|
28
46
|
erubi (~> 1.4)
|
|
29
47
|
rails-dom-testing (~> 2.0)
|
|
30
|
-
rails-html-sanitizer (~> 1.
|
|
31
|
-
|
|
48
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
49
|
+
activejob (6.0.0)
|
|
50
|
+
activesupport (= 6.0.0)
|
|
51
|
+
globalid (>= 0.3.6)
|
|
52
|
+
activemodel (6.0.0)
|
|
53
|
+
activesupport (= 6.0.0)
|
|
54
|
+
activerecord (6.0.0)
|
|
55
|
+
activemodel (= 6.0.0)
|
|
56
|
+
activesupport (= 6.0.0)
|
|
57
|
+
activestorage (6.0.0)
|
|
58
|
+
actionpack (= 6.0.0)
|
|
59
|
+
activejob (= 6.0.0)
|
|
60
|
+
activerecord (= 6.0.0)
|
|
61
|
+
marcel (~> 0.3.1)
|
|
62
|
+
activesupport (6.0.0)
|
|
32
63
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
33
64
|
i18n (>= 0.7, < 2)
|
|
34
65
|
minitest (~> 5.1)
|
|
35
66
|
tzinfo (~> 1.1)
|
|
67
|
+
zeitwerk (~> 2.1, >= 2.1.8)
|
|
36
68
|
ast (2.4.0)
|
|
37
69
|
builder (3.2.3)
|
|
38
|
-
cable_ready (4.0.
|
|
39
|
-
|
|
70
|
+
cable_ready (4.0.3)
|
|
71
|
+
rails (>= 5.2)
|
|
72
|
+
coderay (1.1.2)
|
|
40
73
|
concurrent-ruby (1.1.5)
|
|
41
74
|
crass (1.0.4)
|
|
42
75
|
erubi (1.8.0)
|
|
76
|
+
globalid (0.4.2)
|
|
77
|
+
activesupport (>= 4.2.0)
|
|
43
78
|
i18n (1.6.0)
|
|
44
79
|
concurrent-ruby (~> 1.0)
|
|
45
80
|
jaro_winkler (1.5.3)
|
|
46
81
|
loofah (2.2.3)
|
|
47
82
|
crass (~> 1.0.2)
|
|
48
83
|
nokogiri (>= 1.5.9)
|
|
84
|
+
mail (2.7.1)
|
|
85
|
+
mini_mime (>= 0.1.1)
|
|
86
|
+
marcel (0.3.3)
|
|
87
|
+
mimemagic (~> 0.3.2)
|
|
88
|
+
method_source (0.9.2)
|
|
89
|
+
mimemagic (0.3.3)
|
|
90
|
+
mini_mime (1.0.2)
|
|
49
91
|
mini_portile2 (2.4.0)
|
|
50
92
|
minitest (5.11.3)
|
|
51
93
|
nio4r (2.4.0)
|
|
52
|
-
nokogiri (1.10.
|
|
94
|
+
nokogiri (1.10.4)
|
|
53
95
|
mini_portile2 (~> 2.4.0)
|
|
54
96
|
parallel (1.17.0)
|
|
55
97
|
parser (2.6.3.0)
|
|
56
98
|
ast (~> 2.4.0)
|
|
99
|
+
pry (0.12.2)
|
|
100
|
+
coderay (~> 1.1.0)
|
|
101
|
+
method_source (~> 0.9.0)
|
|
102
|
+
pry-nav (0.3.0)
|
|
103
|
+
pry (>= 0.9.10, < 0.13.0)
|
|
57
104
|
rack (2.0.7)
|
|
58
105
|
rack-test (1.1.0)
|
|
59
106
|
rack (>= 1.0, < 3)
|
|
107
|
+
rails (6.0.0)
|
|
108
|
+
actioncable (= 6.0.0)
|
|
109
|
+
actionmailbox (= 6.0.0)
|
|
110
|
+
actionmailer (= 6.0.0)
|
|
111
|
+
actionpack (= 6.0.0)
|
|
112
|
+
actiontext (= 6.0.0)
|
|
113
|
+
actionview (= 6.0.0)
|
|
114
|
+
activejob (= 6.0.0)
|
|
115
|
+
activemodel (= 6.0.0)
|
|
116
|
+
activerecord (= 6.0.0)
|
|
117
|
+
activestorage (= 6.0.0)
|
|
118
|
+
activesupport (= 6.0.0)
|
|
119
|
+
bundler (>= 1.3.0)
|
|
120
|
+
railties (= 6.0.0)
|
|
121
|
+
sprockets-rails (>= 2.0.0)
|
|
60
122
|
rails-dom-testing (2.0.3)
|
|
61
123
|
activesupport (>= 4.2.0)
|
|
62
124
|
nokogiri (>= 1.6)
|
|
63
125
|
rails-html-sanitizer (1.2.0)
|
|
64
126
|
loofah (~> 2.2, >= 2.2.2)
|
|
127
|
+
railties (6.0.0)
|
|
128
|
+
actionpack (= 6.0.0)
|
|
129
|
+
activesupport (= 6.0.0)
|
|
130
|
+
method_source
|
|
131
|
+
rake (>= 0.8.7)
|
|
132
|
+
thor (>= 0.20.3, < 2.0)
|
|
65
133
|
rainbow (3.0.0)
|
|
66
134
|
rake (12.3.3)
|
|
67
135
|
rubocop (0.72.0)
|
|
@@ -74,11 +142,19 @@ GEM
|
|
|
74
142
|
rubocop-performance (1.4.1)
|
|
75
143
|
rubocop (>= 0.71.0)
|
|
76
144
|
ruby-progressbar (1.10.1)
|
|
145
|
+
sprockets (3.7.2)
|
|
146
|
+
concurrent-ruby (~> 1.0)
|
|
147
|
+
rack (> 1, < 3)
|
|
148
|
+
sprockets-rails (3.2.1)
|
|
149
|
+
actionpack (>= 4.0)
|
|
150
|
+
activesupport (>= 4.0)
|
|
151
|
+
sprockets (>= 3.0.0)
|
|
77
152
|
standard (0.1.2)
|
|
78
153
|
rubocop (~> 0.72.0)
|
|
79
154
|
rubocop-performance (~> 1.4.0)
|
|
80
155
|
standardrb (1.0.0)
|
|
81
156
|
standard
|
|
157
|
+
thor (0.20.3)
|
|
82
158
|
thread_safe (0.3.6)
|
|
83
159
|
tzinfo (1.2.5)
|
|
84
160
|
thread_safe (~> 0.1)
|
|
@@ -86,15 +162,18 @@ GEM
|
|
|
86
162
|
websocket-driver (0.7.1)
|
|
87
163
|
websocket-extensions (>= 0.1.0)
|
|
88
164
|
websocket-extensions (0.1.4)
|
|
165
|
+
zeitwerk (2.1.9)
|
|
89
166
|
|
|
90
167
|
PLATFORMS
|
|
91
168
|
ruby
|
|
92
169
|
|
|
93
170
|
DEPENDENCIES
|
|
94
171
|
bundler (~> 2.0)
|
|
172
|
+
pry
|
|
173
|
+
pry-nav
|
|
95
174
|
rake
|
|
96
175
|
standardrb
|
|
97
176
|
stimulus_reflex!
|
|
98
177
|
|
|
99
178
|
BUNDLED WITH
|
|
100
|
-
2.0.
|
|
179
|
+
2.0.2
|
data/README.md
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
|
-
[](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
|
|
2
2
|
[](https://codeclimate.com/github/hopsoft/stimulus_reflex/maintainability)
|
|
3
3
|
|
|
4
4
|
# StimulusReflex
|
|
5
5
|
|
|
6
|
-
###
|
|
6
|
+
### Build reactive [Single Page Applications (SPAs)](https://en.wikipedia.org/wiki/Single-page_application) with [Rails](https://rubyonrails.org) and [Stimulus](https://stimulusjs.org)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
This project supports building [reactive applications](https://en.wikipedia.org/wiki/Reactive_programming)
|
|
9
|
+
with the Rails tooling you already know and love.
|
|
10
|
+
It's designed to work perfectly with [server rendered HTML](https://guides.rubyonrails.org/action_view_overview.html),
|
|
11
|
+
[Russian doll caching](https://edgeguides.rubyonrails.org/caching_with_rails.html#russian-doll-caching),
|
|
12
|
+
[Stimulus](https://stimulusjs.org), [Turbolinks](https://www.youtube.com/watch?v=SWEts0rlezA), etc...
|
|
9
13
|
|
|
10
|
-
This project aims to support the building of [Single Page Applications (SPAs)](https://en.wikipedia.org/wiki/Single-page_application)
|
|
11
|
-
with standard Rails tooling. Think server rendered HTML, Stimulus, Turbolinks, etc...
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
__No need for a complex front-end framework. No need to grow your team or duplicate your efforts.__
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
> The lifecycle of a "modern" SPA app is so convoluted, it requires a team to build and support.
|
|
20
|
+
> The wire size and computation demands of these heavy client sites frequently run slower than the server-rendered pages that they replaced.
|
|
21
|
+
> With Stimulus Reflex, a Rails developer can build Single Page Applications without the need for client rendering or heavy JS frameworks.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
_Inspired by [Phoenix LiveView](https://youtu.be/Z2DU0qLfPIY?t=670)._ 🙌
|
|
14
26
|
|
|
15
27
|
## How it Works
|
|
16
28
|
|
|
17
|
-
1.
|
|
29
|
+
1. Render a standard Rails view template
|
|
30
|
+
1. Use [Stimulus](https://stimulusjs.org) and [ActionCable](https://edgeguides.rubyonrails.org/action_cable_overview.html) to invoke a method on the server
|
|
18
31
|
1. Watch the page automatically render updates via fast [DOM diffing](https://github.com/patrick-steele-idem/morphdom)
|
|
19
32
|
1. That's it...
|
|
20
33
|
|
|
21
34
|
__Yes, it really is that simple.__
|
|
22
|
-
Just create a server rendered HTML page and send RPC calls to the server via web socket.
|
|
23
35
|
There are no hidden gotchas.
|
|
24
36
|
|
|
25
37
|

|
|
@@ -64,7 +76,7 @@ export default class extends Controller {
|
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
increment() {
|
|
67
|
-
// trigger a server
|
|
79
|
+
// trigger a server-side reflex and a client-side page update
|
|
68
80
|
this.stimulate('ExampleReflex#increment', 1);
|
|
69
81
|
}
|
|
70
82
|
}
|
|
@@ -75,7 +87,7 @@ export default class extends Controller {
|
|
|
75
87
|
```ruby
|
|
76
88
|
class ExampleReflex < StimulusReflex::Reflex
|
|
77
89
|
def increment(step = 1)
|
|
78
|
-
@count = @count.to_i
|
|
90
|
+
@count = @count.to_i + step
|
|
79
91
|
end
|
|
80
92
|
end
|
|
81
93
|
```
|
|
@@ -93,12 +105,22 @@ The following happens after the `StimulusReflex::Reflex` method call finishes.
|
|
|
93
105
|
StimulusReflex will use the ActionCable defaults of `window.App` and `App.cable` if they exist.
|
|
94
106
|
If these defaults do not exist, StimulusReflex will establish a new socket connection.
|
|
95
107
|
|
|
108
|
+
### Performance
|
|
109
|
+
|
|
110
|
+
ActionCable emits verbose log messages. Disabling ActionCable logs may improve performance.
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
# config/application.rb
|
|
114
|
+
|
|
115
|
+
ActionCable.server.config.logger = Logger.new(nil)
|
|
116
|
+
```
|
|
117
|
+
|
|
96
118
|
### ActionCable Rooms
|
|
97
119
|
|
|
98
120
|
You may find the need to restrict notifications to a specific room.
|
|
99
121
|
This can be accomplished by setting the `data-room` attribute on the StimulusController element.
|
|
100
122
|
|
|
101
|
-
```
|
|
123
|
+
```erb
|
|
102
124
|
<a href="#" data-controller="example" data-action="click->example#increment" data-room="12345">
|
|
103
125
|
```
|
|
104
126
|
|
|
@@ -118,3 +140,17 @@ export default class extends Controller {
|
|
|
118
140
|
```
|
|
119
141
|
|
|
120
142
|
The default value is `25`.
|
|
143
|
+
|
|
144
|
+
## Demo Applications
|
|
145
|
+
|
|
146
|
+
Building apps with StimulusReflex should evoke your memories of the original [Rails demo video](https://www.youtube.com/watch?v=Gzj723LkRJY).
|
|
147
|
+
|
|
148
|
+
> Look at all the things I'm **not** doing. -DHH
|
|
149
|
+
|
|
150
|
+
- [TodoMVC](https://github.com/hopsoft/stimulus_reflex_todomvc)
|
|
151
|
+
|
|
152
|
+
## Contributing
|
|
153
|
+
|
|
154
|
+
This project uses [Standard](https://github.com/testdouble/standard)
|
|
155
|
+
and [Prettier](https://github.com/prettier/prettier) to minimize bike shedding related to code formatting.
|
|
156
|
+
Please run `./bin/standardize` prior submitting pull requests.
|
data/README.md.orig
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
[](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
|
|
2
|
+
[](https://codeclimate.com/github/hopsoft/stimulus_reflex/maintainability)
|
|
3
|
+
|
|
4
|
+
# StimulusReflex
|
|
5
|
+
|
|
6
|
+
### Build reactive [Single Page Applications (SPAs)](https://en.wikipedia.org/wiki/Single-page_application) with [Rails](https://rubyonrails.org) and [Stimulus](https://stimulusjs.org)
|
|
7
|
+
|
|
8
|
+
This project supports building [reactive applications](https://en.wikipedia.org/wiki/Reactive_programming)
|
|
9
|
+
with the Rails tooling you already know and love.
|
|
10
|
+
It's designed to work perfectly with [server rendered HTML](https://guides.rubyonrails.org/action_view_overview.html),
|
|
11
|
+
[Russian doll caching](https://edgeguides.rubyonrails.org/caching_with_rails.html#russian-doll-caching),
|
|
12
|
+
[Stimulus](https://stimulusjs.org), [Turbolinks](https://www.youtube.com/watch?v=SWEts0rlezA), etc...
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
__No need for a complex front-end framework. No need to grow your team or duplicate your efforts.__
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
> The lifecycle of a "modern" SPA app is so convoluted, it requires a team to build and support.
|
|
20
|
+
> The wire size and computation demands of these heavy client sites frequently run slower than the server-rendered pages that they replaced.
|
|
21
|
+
> With Stimulus Reflex, a Rails developer can build Single Page Applications without the need for client rendering or heavy JS frameworks.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
_Inspired by [Phoenix LiveView](https://youtu.be/Z2DU0qLfPIY?t=670)._ 🙌
|
|
26
|
+
|
|
27
|
+
## How it Works
|
|
28
|
+
|
|
29
|
+
1. Render a standard Rails view template
|
|
30
|
+
1. Use [Stimulus](https://stimulusjs.org) and [ActionCable](https://edgeguides.rubyonrails.org/action_cable_overview.html) to invoke a method on the server
|
|
31
|
+
1. Watch the page automatically render updates via fast [DOM diffing](https://github.com/patrick-steele-idem/morphdom)
|
|
32
|
+
1. That's it...
|
|
33
|
+
|
|
34
|
+
__Yes, it really is that simple.__
|
|
35
|
+
There are no hidden gotchas.
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
## Setup
|
|
40
|
+
|
|
41
|
+
### JavaScript
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
yarn add stimulus_reflex
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Gemfile
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
gem "stimulus_reflex"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Basic Usage
|
|
54
|
+
|
|
55
|
+
### app/views/pages/example.html.erb
|
|
56
|
+
|
|
57
|
+
```erb
|
|
58
|
+
<head></head>
|
|
59
|
+
<body>
|
|
60
|
+
<a href="#" data-controller="example" data-action="click->example#increment">
|
|
61
|
+
Increment <%= @count.to_i %>
|
|
62
|
+
</a>
|
|
63
|
+
</body>
|
|
64
|
+
</html>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### app/javascript/controllers/example.js
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
import { Controller } from "stimulus"
|
|
71
|
+
import StimulusReflex from "stimulus_reflex"
|
|
72
|
+
|
|
73
|
+
export default class extends Controller {
|
|
74
|
+
connect() {
|
|
75
|
+
StimulusReflex.register(this);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
increment() {
|
|
79
|
+
// trigger a server-side reflex and a client-side page update
|
|
80
|
+
this.stimulate('ExampleReflex#increment', 1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### app/reflexes/example_reflex.rb
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
class ExampleReflex < StimulusReflex::Reflex
|
|
89
|
+
def increment(step = 1)
|
|
90
|
+
@count = @count.to_i + step
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The following happens after the `StimulusReflex::Reflex` method call finishes.
|
|
96
|
+
|
|
97
|
+
1. The page that triggered the reflex is re-rerendered. _Instance variables created in the reflex are available to both the controller and view templates._
|
|
98
|
+
2. The re-rendered HTML is sent to the client over the ActionCable socket.
|
|
99
|
+
3. The page is updated via fast DOM diffing courtesy of morphdom. _While future versions of StimulusReflex might support more granular updates, today the entire body is re-rendered and sent over the socket._
|
|
100
|
+
|
|
101
|
+
## Advanced Usage
|
|
102
|
+
|
|
103
|
+
### ActionCable
|
|
104
|
+
|
|
105
|
+
StimulusReflex will use the ActionCable defaults of `window.App` and `App.cable` if they exist.
|
|
106
|
+
If these defaults do not exist, StimulusReflex will establish a new socket connection.
|
|
107
|
+
|
|
108
|
+
### Performance
|
|
109
|
+
|
|
110
|
+
ActionCable emits verbose log messages. Disabling ActionCable logs may improve performance.
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
# config/application.rb
|
|
114
|
+
|
|
115
|
+
ActionCable.server.config.logger = Logger.new(nil)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### ActionCable Rooms
|
|
119
|
+
|
|
120
|
+
You may find the need to restrict notifications to a specific room.
|
|
121
|
+
This can be accomplished by setting the `data-room` attribute on the StimulusController element.
|
|
122
|
+
|
|
123
|
+
```erb
|
|
124
|
+
<a href="#" data-controller="example" data-action="click->example#increment" data-room="12345">
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Render Delay
|
|
128
|
+
|
|
129
|
+
An attempt is made to reduce repaint/reflow jitter when users trigger lots of updates.
|
|
130
|
+
|
|
131
|
+
You can control how long to wait _(think debounce)_ prior to updating the page.
|
|
132
|
+
Simply set the `renderDelay` _(milliseconds)_ option when registering the controller.
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
export default class extends Controller {
|
|
136
|
+
connect() {
|
|
137
|
+
StimulusReflex.register(this, {renderDelay: 200});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The default value is `25`.
|
|
143
|
+
|
|
144
|
+
## Demo Applications
|
|
145
|
+
|
|
146
|
+
Building apps with StimulusReflex should evoke your memories of the original [Rails demo video](https://www.youtube.com/watch?v=Gzj723LkRJY).
|
|
147
|
+
|
|
148
|
+
> Look at all the things I'm **not** doing. -DHH
|
|
149
|
+
|
|
150
|
+
- [TodoMVC](https://github.com/hopsoft/stimulus_reflex_todomvc)
|
|
151
|
+
|
|
152
|
+
<<<<<<< HEAD
|
|
153
|
+
## Contributing
|
|
154
|
+
|
|
155
|
+
This project uses [Standard](https://github.com/testdouble/standard)
|
|
156
|
+
and [Prettier](https://github.com/prettier/prettier) to minimize bike shedding related to code formatting.
|
|
157
|
+
Please run `./bin/standardize` prior submitting pull requests.
|
|
158
|
+
=======
|
|
159
|
+
>>>>>>> master
|
data/bin/console
CHANGED
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
require "bundler/setup"
|
|
4
4
|
require "stimulus_reflex"
|
|
5
|
+
require "pry"
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
-
|
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
-
# require "pry"
|
|
11
|
-
# Pry.start
|
|
12
|
-
|
|
13
|
-
require "irb"
|
|
14
|
-
IRB.start(__FILE__)
|
|
7
|
+
Pry.start
|
data/bin/standardize
CHANGED
data/lib/stimulus_reflex.rb
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
require "uri"
|
|
2
|
+
require "rack"
|
|
3
|
+
require "rails/engine"
|
|
4
|
+
require "active_support/all"
|
|
5
|
+
require "action_dispatch"
|
|
6
|
+
require "action_cable"
|
|
7
|
+
require "nokogiri"
|
|
8
|
+
require "cable_ready"
|
|
1
9
|
require "stimulus_reflex/version"
|
|
2
10
|
require "stimulus_reflex/reflex"
|
|
3
11
|
require "stimulus_reflex/channel"
|
|
4
12
|
|
|
5
13
|
module StimulusReflex
|
|
6
|
-
|
|
7
|
-
class Engine < ::Rails::Engine
|
|
8
|
-
end
|
|
14
|
+
class Engine < Rails::Engine
|
|
9
15
|
end
|
|
10
16
|
end
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
require "uri"
|
|
2
|
-
require "rack"
|
|
3
|
-
require "nokogiri"
|
|
4
|
-
require "active_support/all"
|
|
5
|
-
require "action_dispatch"
|
|
6
|
-
require "cable_ready"
|
|
7
|
-
|
|
8
1
|
class StimulusReflex::Channel < ActionCable::Channel::Base
|
|
9
2
|
include CableReady::Broadcaster
|
|
10
3
|
|
|
@@ -22,38 +15,33 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
|
|
|
22
15
|
end
|
|
23
16
|
|
|
24
17
|
def receive(data)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
arguments = data["args"] || []
|
|
18
|
+
url = data["url"].to_s
|
|
19
|
+
target = data["target"].to_s
|
|
20
|
+
reflex_name, method_name = target.split("#")
|
|
21
|
+
reflex_name = reflex_name.classify
|
|
22
|
+
arguments = data["args"] || []
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
begin
|
|
25
|
+
reflex = reflex_name.constantize.new(self, url: url)
|
|
26
|
+
delegate_call_to_reflex reflex, method_name, arguments
|
|
27
|
+
rescue => invoke_error
|
|
28
|
+
logger.error "StimulusReflex::Channel Failed to invoke #{target}! #{url} #{invoke_error}"
|
|
29
|
+
end
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
end
|
|
31
|
+
begin
|
|
32
|
+
render_page_and_broadcast_morph url, reflex
|
|
33
|
+
rescue => render_error
|
|
34
|
+
logger.error "StimulusReflex::Channel Failed to rerender #{url} #{render_error}"
|
|
44
35
|
end
|
|
45
36
|
end
|
|
46
37
|
|
|
47
38
|
private
|
|
48
39
|
|
|
49
40
|
def delegate_call_to_reflex(reflex, method_name, arguments = [])
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
else
|
|
55
|
-
reflex.send method_name
|
|
56
|
-
end
|
|
41
|
+
if reflex.method(method_name).arity != 0
|
|
42
|
+
reflex.send method_name, *arguments
|
|
43
|
+
else
|
|
44
|
+
reflex.send method_name
|
|
57
45
|
end
|
|
58
46
|
end
|
|
59
47
|
|
|
@@ -63,46 +51,40 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
|
|
|
63
51
|
end
|
|
64
52
|
|
|
65
53
|
def render_page(url, reflex)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
controller.instance_variable_set
|
|
73
|
-
|
|
74
|
-
controller.instance_variable_set name, reflex.instance_variable_get(name)
|
|
75
|
-
end
|
|
54
|
+
uri = URI.parse(url)
|
|
55
|
+
url_params = Rails.application.routes.recognize_path(url)
|
|
56
|
+
controller_class = "#{url_params[:controller]}_controller".classify.constantize
|
|
57
|
+
controller = controller_class.new
|
|
58
|
+
controller.instance_variable_set :"@stimulus_reflex", true
|
|
59
|
+
reflex.instance_variables.each do |name|
|
|
60
|
+
controller.instance_variable_set name, reflex.instance_variable_get(name)
|
|
61
|
+
end
|
|
76
62
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
63
|
+
query_hash = Rack::Utils.parse_nested_query(uri.query)
|
|
64
|
+
env = {
|
|
65
|
+
"action_dispatch.request.path_parameters" => url_params,
|
|
66
|
+
"action_dispatch.request.query_parameters" => query_hash,
|
|
67
|
+
"rack.request.query_hash" => query_hash,
|
|
68
|
+
"rack.request.query_string" => uri.query,
|
|
69
|
+
"ORIGINAL_SCRIPT_NAME" => "",
|
|
70
|
+
"ORIGINAL_FULLPATH" => uri.path,
|
|
71
|
+
Rack::SCRIPT_NAME => "",
|
|
72
|
+
Rack::PATH_INFO => uri.path,
|
|
73
|
+
Rack::REQUEST_PATH => uri.path,
|
|
74
|
+
Rack::QUERY_STRING => uri.query,
|
|
75
|
+
}
|
|
90
76
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
97
|
-
html
|
|
77
|
+
request = ActionDispatch::Request.new(connection.env.merge(env))
|
|
78
|
+
controller.request = request
|
|
79
|
+
controller.response = ActionDispatch::Response.new
|
|
80
|
+
controller.process url_params[:action]
|
|
81
|
+
controller.response.body
|
|
98
82
|
end
|
|
99
83
|
|
|
100
84
|
def broadcast_morph(url, html)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
cable_ready.broadcast
|
|
105
|
-
end
|
|
85
|
+
html = extract_body_html(html)
|
|
86
|
+
cable_ready[stream_name].morph selector: "body", html: html, children_only: true
|
|
87
|
+
cable_ready.broadcast
|
|
106
88
|
end
|
|
107
89
|
|
|
108
90
|
def extract_body_html(html)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stimulus_reflex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nathan Hopkins
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2019-08-
|
|
12
|
+
date: 2019-08-17 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rack
|
|
@@ -40,63 +40,77 @@ dependencies:
|
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
41
|
version: '0'
|
|
42
42
|
- !ruby/object:Gem::Dependency
|
|
43
|
-
name:
|
|
43
|
+
name: rails
|
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
|
45
45
|
requirements:
|
|
46
46
|
- - ">="
|
|
47
47
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: 5.2
|
|
48
|
+
version: '5.2'
|
|
49
49
|
type: :runtime
|
|
50
50
|
prerelease: false
|
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
|
52
52
|
requirements:
|
|
53
53
|
- - ">="
|
|
54
54
|
- !ruby/object:Gem::Version
|
|
55
|
-
version: 5.2
|
|
55
|
+
version: '5.2'
|
|
56
56
|
- !ruby/object:Gem::Dependency
|
|
57
|
-
name:
|
|
57
|
+
name: cable_ready
|
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
|
59
59
|
requirements:
|
|
60
60
|
- - ">="
|
|
61
61
|
- !ruby/object:Gem::Version
|
|
62
|
-
version:
|
|
62
|
+
version: 4.0.3
|
|
63
63
|
type: :runtime
|
|
64
64
|
prerelease: false
|
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
66
66
|
requirements:
|
|
67
67
|
- - ">="
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version:
|
|
69
|
+
version: 4.0.3
|
|
70
70
|
- !ruby/object:Gem::Dependency
|
|
71
|
-
name:
|
|
71
|
+
name: bundler
|
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - "~>"
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '2.0'
|
|
77
|
+
type: :development
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - "~>"
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '2.0'
|
|
84
|
+
- !ruby/object:Gem::Dependency
|
|
85
|
+
name: rake
|
|
72
86
|
requirement: !ruby/object:Gem::Requirement
|
|
73
87
|
requirements:
|
|
74
88
|
- - ">="
|
|
75
89
|
- !ruby/object:Gem::Version
|
|
76
|
-
version:
|
|
77
|
-
type: :
|
|
90
|
+
version: '0'
|
|
91
|
+
type: :development
|
|
78
92
|
prerelease: false
|
|
79
93
|
version_requirements: !ruby/object:Gem::Requirement
|
|
80
94
|
requirements:
|
|
81
95
|
- - ">="
|
|
82
96
|
- !ruby/object:Gem::Version
|
|
83
|
-
version:
|
|
97
|
+
version: '0'
|
|
84
98
|
- !ruby/object:Gem::Dependency
|
|
85
|
-
name:
|
|
99
|
+
name: pry
|
|
86
100
|
requirement: !ruby/object:Gem::Requirement
|
|
87
101
|
requirements:
|
|
88
|
-
- - "
|
|
102
|
+
- - ">="
|
|
89
103
|
- !ruby/object:Gem::Version
|
|
90
|
-
version: '
|
|
104
|
+
version: '0'
|
|
91
105
|
type: :development
|
|
92
106
|
prerelease: false
|
|
93
107
|
version_requirements: !ruby/object:Gem::Requirement
|
|
94
108
|
requirements:
|
|
95
|
-
- - "
|
|
109
|
+
- - ">="
|
|
96
110
|
- !ruby/object:Gem::Version
|
|
97
|
-
version: '
|
|
111
|
+
version: '0'
|
|
98
112
|
- !ruby/object:Gem::Dependency
|
|
99
|
-
name:
|
|
113
|
+
name: pry-nav
|
|
100
114
|
requirement: !ruby/object:Gem::Requirement
|
|
101
115
|
requirements:
|
|
102
116
|
- - ">="
|
|
@@ -135,6 +149,7 @@ files:
|
|
|
135
149
|
- Gemfile.lock
|
|
136
150
|
- LICENSE.txt
|
|
137
151
|
- README.md
|
|
152
|
+
- README.md.orig
|
|
138
153
|
- Rakefile
|
|
139
154
|
- bin/console
|
|
140
155
|
- bin/setup
|
|
@@ -165,5 +180,5 @@ requirements: []
|
|
|
165
180
|
rubygems_version: 3.0.3
|
|
166
181
|
signing_key:
|
|
167
182
|
specification_version: 4
|
|
168
|
-
summary: Build
|
|
183
|
+
summary: Build reactive Single Page Applications (SPAs) with Rails and Stimulus
|
|
169
184
|
test_files: []
|