stimulus_reflex 0.2.0 → 0.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: 497c626308ac98e461cd46fab1fc85b0eacdbfaa00fd69d5932633b37dcae7d7
4
- data.tar.gz: 45c12660b36b162c69f02f8aa1e868d97bb730672a942c8116222a2e26740496
3
+ metadata.gz: 8544fe68bac22a31e14a433b4306f8f461af53a6962b0d882f96d5f457ccf284
4
+ data.tar.gz: f78fa38dfe275df2a6e8db37285abae01787877a408141f204ec6d22cc98e605
5
5
  SHA512:
6
- metadata.gz: ae445693f9ac599962ea2b043186bba99d969540f52be386d2e4c628aad03fed1d1326ffb02f7eb8931a253136d03866d6cfe4986a2c62a66a8446eb8e455a2b
7
- data.tar.gz: 5fb5e051e113489b33cdce9c433fa14c41b5881a096927ac9b3ec0a71265c946bca83e65a650a9930745d85aaeb9c09a727cbac685978f34dd15631449ac1b07
6
+ metadata.gz: cc7cc420fa4b6783b6446964eae9d07905bc0c261683710c3d67db4378bd947f5a8acbde4bf047d242155ba3d25ea6fc971675c47de4364bf69f62001ff98cb5
7
+ data.tar.gz: e18ac0934a7d2b4a7914662a1364f1a9cdc5cb42c87043fd2a6cea88292aed02e03474f391de359325d13db86dfb524434c9b4e6e3c6c37e4a10e0c50092bab4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stimulus_reflex (0.2.0)
4
+ stimulus_reflex (0.3.0)
5
5
  actioncable (>= 5.2.1)
6
6
  actionpack (>= 5.2.1)
7
7
  cable_ready (>= 2.0.7)
@@ -11,44 +11,51 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- actioncable (5.2.1)
15
- actionpack (= 5.2.1)
14
+ actioncable (5.2.2)
15
+ actionpack (= 5.2.2)
16
16
  nio4r (~> 2.0)
17
17
  websocket-driver (>= 0.6.1)
18
- actionpack (5.2.1)
19
- actionview (= 5.2.1)
20
- activesupport (= 5.2.1)
18
+ actionpack (5.2.2)
19
+ actionview (= 5.2.2)
20
+ activesupport (= 5.2.2)
21
21
  rack (~> 2.0)
22
22
  rack-test (>= 0.6.3)
23
23
  rails-dom-testing (~> 2.0)
24
24
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
25
- actionview (5.2.1)
26
- activesupport (= 5.2.1)
25
+ actionview (5.2.2)
26
+ activesupport (= 5.2.2)
27
27
  builder (~> 3.1)
28
28
  erubi (~> 1.4)
29
29
  rails-dom-testing (~> 2.0)
30
30
  rails-html-sanitizer (~> 1.0, >= 1.0.3)
31
- activesupport (5.2.1)
31
+ activesupport (5.2.2)
32
32
  concurrent-ruby (~> 1.0, >= 1.0.2)
33
33
  i18n (>= 0.7, < 2)
34
34
  minitest (~> 5.1)
35
35
  tzinfo (~> 1.1)
36
+ ast (2.4.0)
36
37
  builder (3.2.3)
37
- cable_ready (2.0.7)
38
+ cable_ready (2.0.8)
38
39
  activesupport (>= 5.0.0)
39
- concurrent-ruby (1.1.3)
40
+ concurrent-ruby (1.1.4)
40
41
  crass (1.0.4)
41
- erubi (1.7.1)
42
- i18n (1.1.1)
42
+ erubi (1.8.0)
43
+ i18n (1.5.3)
43
44
  concurrent-ruby (~> 1.0)
45
+ jaro_winkler (1.5.2)
44
46
  loofah (2.2.3)
45
47
  crass (~> 1.0.2)
46
48
  nokogiri (>= 1.5.9)
47
- mini_portile2 (2.3.0)
49
+ mini_portile2 (2.4.0)
48
50
  minitest (5.11.3)
49
51
  nio4r (2.3.1)
50
- nokogiri (1.8.5)
51
- mini_portile2 (~> 2.3.0)
52
+ nokogiri (1.10.1)
53
+ mini_portile2 (~> 2.4.0)
54
+ parallel (1.13.0)
55
+ parser (2.6.0.0)
56
+ ast (~> 2.4.0)
57
+ powerpack (0.1.2)
58
+ psych (3.1.0)
52
59
  rack (2.0.6)
53
60
  rack-test (1.1.0)
54
61
  rack (>= 1.0, < 3)
@@ -57,10 +64,26 @@ GEM
57
64
  nokogiri (>= 1.6)
58
65
  rails-html-sanitizer (1.0.4)
59
66
  loofah (~> 2.2, >= 2.2.2)
67
+ rainbow (3.0.0)
60
68
  rake (12.3.1)
69
+ rubocop (0.65.0)
70
+ jaro_winkler (~> 1.5.1)
71
+ parallel (~> 1.10)
72
+ parser (>= 2.5, != 2.5.1.1)
73
+ powerpack (~> 0.1)
74
+ psych (>= 3.1.0)
75
+ rainbow (>= 2.2.2, < 4.0)
76
+ ruby-progressbar (~> 1.7)
77
+ unicode-display_width (~> 1.4.0)
78
+ ruby-progressbar (1.10.0)
79
+ standard (0.0.30)
80
+ rubocop (>= 0.63)
81
+ standardrb (1.0.0)
82
+ standard
61
83
  thread_safe (0.3.6)
62
84
  tzinfo (1.2.5)
63
85
  thread_safe (~> 0.1)
86
+ unicode-display_width (1.4.1)
64
87
  websocket-driver (0.7.0)
65
88
  websocket-extensions (>= 0.1.0)
66
89
  websocket-extensions (0.1.3)
@@ -71,7 +94,8 @@ PLATFORMS
71
94
  DEPENDENCIES
72
95
  bundler (~> 1.16)
73
96
  rake
97
+ standardrb
74
98
  stimulus_reflex!
75
99
 
76
100
  BUNDLED WITH
77
- 1.16.6
101
+ 1.17.2
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # StimulusReflex
5
5
 
6
- #### Server side reactive behavior for Stimulus controllers
6
+ #### Server side reactive behavior for Stimulus
7
7
 
8
8
  Add the benefits of single page apps (SPA) to server rendered Rails/Stimulus projects with a minimal investment of time, resources, and complexity.
9
9
  _The goal is to provide 80% of the benefits of SPAs with 20% of the typical effort._
@@ -12,28 +12,51 @@ _The goal is to provide 80% of the benefits of SPAs with 20% of the typical effo
12
12
 
13
13
  ## Usage
14
14
 
15
+ ### Gemfile
16
+
15
17
  ```ruby
16
- # Gemfile
17
18
  gem "stimulus_reflex"
18
19
  ```
19
20
 
21
+ ### app/views/layouts/application.html.erb
22
+
23
+ ```erb
24
+ <html>
25
+ <head></head>
26
+ <body data-cable>
27
+ <%= yield %>
28
+ </body>
29
+ </html>
30
+ ```
31
+
32
+ Pages must opt in to establish the ActionCable connection.
33
+ This eliminates unauthorized connection attempts.
34
+
35
+ SEE: https://gist.github.com/hopsoft/02dfdf4456b3ac52f4eaf242289bdd36
36
+
37
+ ### app/assets/javascripts/cable.js
38
+
20
39
  ```javascript
21
- // app/assets/javascripts/cable.js
40
+ //= require action_cable
22
41
  //= require cable_ready
23
42
  //= require stimulus_reflex
43
+ //= require_self
44
+ //= require_tree ./channels
45
+
46
+ (function() {
47
+ document.addEventListener('DOMContentLoaded', function () {
48
+ if (document.querySelector('body[data-cable]')) {
49
+ // be defensive since stimulus_reflex also initializes this.App and App.cable
50
+ this.App || (this.App = {});
51
+ App.cable || (App.cable = ActionCable.createConsumer());
52
+ }
53
+ });
54
+ }.call(this));
24
55
  ```
25
56
 
26
- ```erb
27
- <!-- app/views/layouts/application.html.erb -->
28
- <!-- Opt-in to establish the ActionCable connection -->
29
- <!-- SEE: https://gist.github.com/hopsoft/02dfdf4456b3ac52f4eaf242289bdd36 -->
30
- <body data-cable>
31
- <%= yield %>
32
- </body>
33
- ```
57
+ ### app/javascript/controllers/example.js
34
58
 
35
59
  ```javascript
36
- // app/javascript/controllers/example.js
37
60
  import { Controller } from "stimulus"
38
61
 
39
62
  export default class extends Controller {
@@ -42,24 +65,32 @@ export default class extends Controller {
42
65
  }
43
66
 
44
67
  doStuff() {
45
- this.send('Example#do_stuff', arg1, arg2, ...);
68
+ // trigger a server side reflex and a re-render
69
+ this.stimulate('ExampleReflex#do_stuff', arg1, arg2, ...);
46
70
  }
47
71
  }
48
72
  ```
49
73
 
74
+ ### app/reflexes/example_reflex.rb
75
+
50
76
  ```ruby
51
- # app/stimulus_controllers/example_stimulus_controller.rb
52
- class ExampleStimulusController < StimulusReflex::Controller
77
+ class ExampleReflex < StimulusReflex::Reflex
53
78
  def do_stuff(arg1, arg2, ...)
54
- # hard work...
55
- # 1. the page that triggered this call will rererender
56
- # 2. the HTML will be sent over the ActionCable socket
57
- # 3. client side JavaScript will DOM diff and mutate only the changed nodes
79
+ # stuff...
58
80
  end
59
81
  end
60
82
  ```
61
83
 
62
- Note that ActionCable defaults are expected. This library will use or create `window.App` and `App.cable`.
84
+ The magic happens after the `StimulusReflex::Reflex` method call finishes.
85
+
86
+ 1. The page that triggered the reflex is re-rerendered
87
+ 1. The re-rendered HTML is sent over the ActionCable socket
88
+ 1. The client side DOM diffs the existing page's HTML with the fresh HTML and applies DOM updates for the change delta
89
+
90
+ ### ActionCable Defaults Expected
91
+
92
+ StimulusReflex will use or create `window.App` and `App.cable`
93
+ and is typically loaded before the default ActionCable initialization code.
63
94
 
64
95
  ## Advanced Usage
65
96
 
@@ -78,7 +109,7 @@ StimulusReflex.renderDelay = 200;
78
109
  SEE: https://guides.rubyonrails.org/active_support_instrumentation.html
79
110
 
80
111
  ```ruby
81
- # wraps the stimulus controller method invocation
112
+ # wraps the stimulus reflex method invocation
82
113
  ActiveSupport::Notifications.subscribe "delegate_call.stimulus_reflex" do |*args|
83
114
  event = ActiveSupport::Notifications::Event.new(*args)
84
115
  Rails.logger.debug "#{event.name} #{event.duration} #{event.payload.inspect}"
@@ -110,5 +141,6 @@ The JavaScript source is located in `app/assets/javascripts/stimulus_reflex/src`
110
141
 
111
142
  ```sh
112
143
  # build the javascript
144
+ ./bin/yarn
113
145
  ./bin/webpack
114
146
  ```
data/Rakefile CHANGED
@@ -1,2 +1,2 @@
1
1
  require "bundler/gem_tasks"
2
- task :default => :spec
2
+ task default: :spec
@@ -1 +1 @@
1
- window.StimulusReflex=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";var r;n.r(t),n.d(t,"register",function(){return u});document.addEventListener("DOMContentLoaded",function(){document.querySelector("body[data-cable]")&&(window.App||(window.App={}),App.cable||(App.cable=ActionCable.createConsumer()),App.stimulusReflex||(App.stimulusReflex=App.cable.subscriptions.create("StimulusReflex::Channel",{received:function(e){e.cableReady&&(clearTimeout(r),r=setTimeout(function(){CableReady.perform(e.operations)},StimulusReflex.renderDelay||400))}})))});var o={send:function(){if(!App.stimulusReflex)throw"ActionCable connection not established! Don't foget to opt-in with: body[data-cable]";clearTimeout(r);var e=Array.prototype.slice.call(arguments),t=e.shift();App.stimulusReflex.send({url:location.href,target:t,args:e})}},u=function(e){return Object.assign(e,o),e}}]);
1
+ window.StimulusReflex=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";var r;n.r(t),n.d(t,"register",function(){return u});document.addEventListener("DOMContentLoaded",function(){document.querySelector("body[data-cable]")&&(window.App||(window.App={}),App.cable||(App.cable=ActionCable.createConsumer()),App.stimulusReflex||(App.stimulusReflex=App.cable.subscriptions.create("StimulusReflex::Channel",{received:function(e){e.cableReady&&(clearTimeout(r),r=setTimeout(function(){CableReady.perform(e.operations)},StimulusReflex.renderDelay||400))}})))});var o={stimulate:function(){if(!App.stimulusReflex)throw"ActionCable connection not established! Don't foget to opt-in with: body[data-cable]";clearTimeout(r);var e=Array.prototype.slice.call(arguments),t=e.shift();App.stimulusReflex.send({url:location.href,target:t,args:e})}},u=function(e){return Object.assign(e,o),e}}]);
@@ -9,9 +9,9 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
9
9
  include CableReady::Broadcaster
10
10
 
11
11
  def stream_name
12
- ids = connection.identifiers.map do |identifier|
12
+ ids = connection.identifiers.map { |identifier|
13
13
  send(identifier).try(:id)
14
- end
14
+ }
15
15
  "#{channel_name}#{ids.join ":"}"
16
16
  end
17
17
 
@@ -21,23 +21,22 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
21
21
 
22
22
  def receive(data)
23
23
  ActiveSupport::Notifications.instrument "receive.stimulus_reflex", data do
24
- start = Time.current
25
24
  url = data["url"].to_s
26
25
  target = data["target"].to_s
27
- stimulus_controller_name, method_name = target.split("#")
28
- stimulus_controller_name = "#{stimulus_controller_name.classify}StimulusController"
26
+ reflex_name, method_name = target.split("#")
27
+ reflex_name = reflex_name.classify
29
28
  arguments = data["args"] || []
30
29
 
31
30
  begin
32
- stimulus_controller = stimulus_controller_name.constantize.new(self, url: url)
33
- delegate_call_to_stimulus_controller stimulus_controller, method_name, arguments
34
- rescue StandardError => invoke_error
31
+ reflex = reflex_name.constantize.new(self, url: url)
32
+ delegate_call_to_reflex reflex, method_name, arguments
33
+ rescue => invoke_error
35
34
  logger.error "StimulusReflex::Channel Failed to invoke #{target}! #{url} #{invoke_error}"
36
35
  end
37
36
 
38
37
  begin
39
- render_page_and_broadcast_morph url, stimulus_controller
40
- rescue StandardError => render_error
38
+ render_page_and_broadcast_morph url, reflex
39
+ rescue => render_error
41
40
  logger.error "StimulusReflex::Channel Failed to rerender #{url} #{render_error}"
42
41
  end
43
42
  end
@@ -45,23 +44,23 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
45
44
 
46
45
  private
47
46
 
48
- def delegate_call_to_stimulus_controller(stimulus_controller, method_name, arguments = [])
49
- instrument_payload = {stimulus_controller: stimulus_controller.class.name, method_name: method_name, arguments: arguments.inspect}
47
+ def delegate_call_to_reflex(reflex, method_name, arguments = [])
48
+ instrument_payload = {reflex: reflex.class.name, method_name: method_name, arguments: arguments.inspect}
50
49
  ActiveSupport::Notifications.instrument "delegate_call.stimulus_reflex", instrument_payload do
51
- if stimulus_controller.method(method_name).arity > 0
52
- stimulus_controller.send method_name, *arguments
50
+ if reflex.method(method_name).arity > 0
51
+ reflex.send method_name, *arguments
53
52
  else
54
- stimulus_controller.send method_name
53
+ reflex.send method_name
55
54
  end
56
55
  end
57
56
  end
58
57
 
59
- def render_page_and_broadcast_morph(url, stimulus_controller)
60
- html = render_page(url, stimulus_controller)
58
+ def render_page_and_broadcast_morph(url, reflex)
59
+ html = render_page(url, reflex)
61
60
  broadcast_morph url, html if html.present?
62
61
  end
63
62
 
64
- def render_page(url, stimulus_controller)
63
+ def render_page(url, reflex)
65
64
  html = nil
66
65
  ActiveSupport::Notifications.instrument "render_page.stimulus_reflex", url: url do
67
66
  uri = URI.parse(url)
@@ -69,8 +68,8 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
69
68
  controller_class = "#{url_params[:controller]}_controller".classify.constantize
70
69
  controller = controller_class.new
71
70
  controller.instance_variable_set :"@stimulus_reflex", true
72
- stimulus_controller.instance_variables.each do |name|
73
- controller.instance_variable_set name, stimulus_controller.instance_variable_get(name)
71
+ reflex.instance_variables.each do |name|
72
+ controller.instance_variable_set name, reflex.instance_variable_get(name)
74
73
  end
75
74
 
76
75
  query_hash = Rack::Utils.parse_nested_query(uri.query)
@@ -1,4 +1,4 @@
1
- class StimulusReflex::Controller
1
+ class StimulusReflex::Reflex
2
2
  attr_reader :channel, :url
3
3
 
4
4
  delegate :connection, to: :channel
@@ -1,3 +1,3 @@
1
1
  module StimulusReflex
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,5 +1,5 @@
1
1
  require "stimulus_reflex/version"
2
- require "stimulus_reflex/controller"
2
+ require "stimulus_reflex/reflex"
3
3
  require "stimulus_reflex/channel"
4
4
 
5
5
  module StimulusReflex
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: 0.2.0
4
+ version: 0.3.0
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: 2018-11-16 00:00:00.000000000 Z
12
+ date: 2019-02-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -109,6 +109,20 @@ dependencies:
109
109
  - - ">="
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: standardrb
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
112
126
  description:
113
127
  email:
114
128
  - natehop@gmail.com
@@ -129,7 +143,7 @@ files:
129
143
  - bin/yarn
130
144
  - lib/stimulus_reflex.rb
131
145
  - lib/stimulus_reflex/channel.rb
132
- - lib/stimulus_reflex/controller.rb
146
+ - lib/stimulus_reflex/reflex.rb
133
147
  - lib/stimulus_reflex/version.rb
134
148
  homepage: https://github.com/hopsoft/stimulus_reflex
135
149
  licenses:
@@ -150,9 +164,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
164
  - !ruby/object:Gem::Version
151
165
  version: '0'
152
166
  requirements: []
153
- rubyforge_project:
154
- rubygems_version: 2.7.6
167
+ rubygems_version: 3.0.1
155
168
  signing_key:
156
169
  specification_version: 4
157
- summary: Server side reactive behavior for Stimulus controllers
170
+ summary: Server side reactive behavior for Stimulus
158
171
  test_files: []