stimulus_reflex 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of stimulus_reflex might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce2617cefcb188998c2f9aca1a440bd2501839a699166cdfa32fba44741af5f5
4
- data.tar.gz: a486389eef17cfa47e8fefef2256cd72a2aff25c1d6ce5713cc49d444565f787
3
+ metadata.gz: 8072c82ab1f16ce62c41e6d970952c3762a9e2fe5d87d2036ff2f37af7f3a4fb
4
+ data.tar.gz: b3549d33023d9c27e878443f48391e13b82562e4dc9d9cbfb64b9744d8fe0702
5
5
  SHA512:
6
- metadata.gz: 36f7b68e56c6446b5125d984378f24207bec848fdfeb99365b99dcac3f9b725e20a99fbd093740e22abc8c8d6fae4b16bd9c470d475289adcd25bb4b177a5563
7
- data.tar.gz: ed8f1e225df23c5b949f2c1f6a4f743521f7b6118f621808b19f46d6716fe812b7c6d475149972ad655737806c3612768d9001cc1f6619b41e2732543a6f6fb4
6
+ metadata.gz: 5ba2646379f9bbe65485d947c55467640e890d516ad571f704e064f0fb78956b977ba405d5698efdb6fd3b7e87f1075a9948d59c4b6ec2855410d3b290137a31
7
+ data.tar.gz: 756a22a1a4cb5f1d4ad985dd1424ed15edc3d2e4d8efcf080d3c3a9a551a170fc1a76d84543fd105acc104b97c07d7f377348a00ec329222fa6341c0e627051c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stimulus_reflex (1.1.1)
4
+ stimulus_reflex (2.0.0)
5
5
  cable_ready (>= 4.0.3)
6
6
  nokogiri
7
7
  rack
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
- [![Lines of Code](http://img.shields.io/badge/lines_of_code-203-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
1
+ [![Lines of Code](http://img.shields.io/badge/lines_of_code-218-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
2
2
  [![Maintainability](https://api.codeclimate.com/v1/badges/2b24fdbd1ae37a24bedb/maintainability)](https://codeclimate.com/github/hopsoft/stimulus_reflex/maintainability)
3
+ ![Prettier](https://github.com/hopsoft/stimulus_reflex/workflows/Prettier%20Check%20Action/badge.svg)
4
+ ![StandardRB](https://github.com/hopsoft/stimulus_reflex/workflows/StandardRB%20Check%20Action/badge.svg)
3
5
 
4
6
  # StimulusReflex
5
7
 
@@ -25,14 +27,19 @@ _Inspired by [Phoenix LiveView](https://youtu.be/Z2DU0qLfPIY?t=670)._ 🙌
25
27
  - [How it Works](#how-it-works)
26
28
  - [Setup](#setup)
27
29
  * [JavaScript](#javascript)
30
+ + [app/javascript/controllers/index.js](#appjavascriptcontrollersindexjs)
28
31
  * [Gemfile](#gemfile)
29
- - [Basic Usage](#basic-usage)
30
- * [app/views/pages/example.html.erb](#appviewspagesexamplehtmlerb)
31
- * [app/javascript/controllers/example.js](#appjavascriptcontrollersexamplejs)
32
- * [app/reflexes/example_reflex.rb](#appreflexesexample_reflexrb)
32
+ - [Usage](#usage)
33
+ * [Implicit Declarative Reflexes](#implicit-declarative-reflexes)
34
+ + [app/views/pages/example.html.erb](#appviewspagesexamplehtmlerb)
35
+ + [app/reflexes/example_reflex.rb](#appreflexesexample_reflexrb)
36
+ * [Explicitly Defined Reflexes](#explicitly-defined-reflexes)
37
+ + [app/views/pages/example.html.erb](#appviewspagesexamplehtmlerb-1)
38
+ + [app/javascript/controllers/example.js](#appjavascriptcontrollersexamplejs)
39
+ + [app/reflexes/example_reflex.rb](#appreflexesexample_reflexrb-1)
40
+ - [What Just Happened](#what-just-happened)
33
41
  - [Advanced Usage](#advanced-usage)
34
- * [Reflex Methods](#reflex-methods)
35
- + [The `options` Keyword Argument](#the-options-keyword-argument)
42
+ * [The Reflex `element` property](#the-reflex-element-property)
36
43
  * [ActionCable](#actioncable)
37
44
  + [Performance](#performance)
38
45
  + [ActionCable Rooms](#actioncable-rooms)
@@ -77,6 +84,21 @@ There are no hidden gotchas.
77
84
  ```
78
85
  yarn add stimulus_reflex
79
86
  ```
87
+ #### app/javascript/controllers/index.js
88
+
89
+ This is the file where Stimulus is initialized in your application.
90
+ _Note that your file location may be different._
91
+
92
+ ```javascript
93
+ import { Application } from 'stimulus';
94
+ import { definitionsFromContext } from 'stimulus/webpack-helpers';
95
+ import StimulusReflex from 'stimulus_reflex';
96
+
97
+ const application = Application.start();
98
+ const context = require.context('controllers', true, /_controller\.js$/);
99
+ application.load(definitionsFromContext(context));
100
+ StimulusReflex.initialize(application);
101
+ ```
80
102
 
81
103
  ### Gemfile
82
104
 
@@ -84,9 +106,47 @@ yarn add stimulus_reflex
84
106
  gem "stimulus_reflex"
85
107
  ```
86
108
 
87
- ## Basic Usage
109
+ ## Usage
110
+
111
+ ### Implicit Declarative Reflexes
112
+
113
+ This example shows how to create a reactive feature without the need to write any JavaScript
114
+ other than initializing StimulusReflex itself _([see the setup instructions](#javascript))_. Everything else is managed entirely by HTML and Ruby.
88
115
 
89
- ### app/views/pages/example.html.erb
116
+ #### app/views/pages/example.html.erb
117
+
118
+ ```erb
119
+ <head></head>
120
+ <body>
121
+ <a href="#" data-reflex="click->ExampleReflex#increment" data-step="1" data-count="<%= @count.to_i %>">
122
+ Increment <%= @count.to_i %>
123
+ </a>
124
+ </body>
125
+ </html>
126
+ ```
127
+
128
+ #### app/reflexes/example_reflex.rb
129
+
130
+ ```ruby
131
+ class ExampleReflex < StimulusReflex::Reflex
132
+ def increment
133
+ @count = element.dataset[:count].to_i + element.dataset[:step].to_i
134
+ end
135
+ end
136
+ ```
137
+
138
+ The code above will automatically update the relevant DOM nodes with the updated count whenever the anchor is clicked.
139
+
140
+ __Note that all concerns from managing state to rendering views are handled server side.__
141
+ This technique works regardless of how complex the UI may become.
142
+ For example, we could render multiple instances of `@count` in unrelated sections of the page and they will all update.
143
+
144
+ ### Explicitly Defined Reflexes
145
+
146
+ This example shows how to create a reactive feature by defining an explicit client side
147
+ Stimulus controller to handle the DOM event and trigger the server side reflex.
148
+
149
+ #### app/views/pages/example.html.erb
90
150
 
91
151
  ```erb
92
152
  <head></head>
@@ -98,7 +158,7 @@ gem "stimulus_reflex"
98
158
  </html>
99
159
  ```
100
160
 
101
- ### app/javascript/controllers/example.js
161
+ #### app/javascript/controllers/example.js
102
162
 
103
163
  ```javascript
104
164
  import { Controller } from "stimulus"
@@ -116,7 +176,7 @@ export default class extends Controller {
116
176
  }
117
177
  ```
118
178
 
119
- ### app/reflexes/example_reflex.rb
179
+ #### app/reflexes/example_reflex.rb
120
180
 
121
181
  ```ruby
122
182
  class ExampleReflex < StimulusReflex::Reflex
@@ -126,65 +186,57 @@ class ExampleReflex < StimulusReflex::Reflex
126
186
  end
127
187
  ```
128
188
 
129
- The following happens after the `StimulusReflex::Reflex` method call finishes.
189
+ ## What Just Happened
190
+
191
+ The following happens when a `StimulusReflex::Reflex` is invoked.
130
192
 
131
193
  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._
132
194
  2. The re-rendered HTML is sent to the client over the ActionCable socket.
133
- 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._
134
-
135
- ## Advanced Usage
136
-
137
- ### Reflex Methods
195
+ 3. The page is updated via fast DOM diffing courtesy of morphdom.
138
196
 
139
- #### The `options` Keyword Argument
197
+ _NOTE: While future versions of StimulusReflex may support more granular updates, today the entire body is re-rendered and sent over the socket._
140
198
 
141
- Reflex methods support an _optional_ `options` keyword argument.
142
-
143
- - This is the only supported keyword argument.
144
- - It must appear after ordinal arguments.
145
-
146
- ```ruby
147
- class ExampleReflex < StimulusReflex::Reflex
148
- def work(options: {})
149
- # ...
150
- end
199
+ ## Advanced Usage
151
200
 
152
- def other_work(value, options: {})
153
- # ...
154
- end
155
- end
156
- ```
201
+ ### The Reflex `element` property
157
202
 
158
- The `options` value contains all of the Stimulus controller's
203
+ All reflex methods expose an `element` property.
204
+ This property holds a Hash like data structure that represents the HTML element that triggered the refelx.
205
+ It contains all of the Stimulus controller's
159
206
  [DOM element attributes](https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes) as well as other properties like `checked` and `value`.
160
207
  _Most of the values will be strings._
161
- Here's an example:
162
208
 
163
209
  ```html
164
- <checkbox checked label="Example" data-controller="checkbox" data-value="123" />
210
+ <checkbox id="example"
211
+ label="Example"
212
+ data-controller="checkbox"
213
+ data-value="123"
214
+ checked />
165
215
  ```
166
216
 
167
- The markup above produces the following behavior in a reflex method.
168
-
169
217
  ```ruby
170
218
  class ExampleReflex < StimulusReflex::Reflex
171
- def work(options: {})
172
- options[:checked] # => true
173
- options[:label] # => "Example"
174
- options["data-controller"] # => "checkbox"
175
- options["data-value"] # => "123"
176
- options.dataset[:controller] # => "checkbox"
177
- options.dataset[:value] # => "123"
219
+ def work()
220
+ element[:id] # => the HTML element's id attribute value
221
+ element.dataset # => a Hash that represents the HTML element's dataset
222
+
223
+ element[:id] # => "example"
224
+ element[:checked] # => true
225
+ element[:label] # => "Example"
226
+ element["data-controller"] # => "checkbox"
227
+ element["data-value"] # => "123"
228
+ element.dataset[:controller] # => "checkbox"
229
+ element.dataset[:value] # => "123"
178
230
  end
179
231
  end
180
232
  ```
181
233
 
182
- - `options[:checked]` holds a boolean
183
- - `options[:selected]` holds a boolean
184
- - `options[:value]` holds the [DOM element's value](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#value)
185
- - `select` elements assign `options[:value]` to their selected option's value
186
- - `select` elements with _multiselect_ enabled assign `options[:values]` to their selected options values
187
- - All other values stored in `options` are extracted from the DOM element's attributes
234
+ - `element[:checked]` holds a boolean
235
+ - `element[:selected]` holds a boolean
236
+ - `element[:value]` holds the [DOM element's value](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#value)
237
+ - `select` elements assign `element[:value]` to their selected option's value
238
+ - `select` elements with _multiselect_ enabled assign `element[:values]` to their selected options values
239
+ - All other values exposed in `element` are extracted from the DOM element's attributes
188
240
 
189
241
  ### ActionCable
190
242
 
@@ -249,11 +301,5 @@ Please run `./bin/standardize` prior submitting pull requests.
249
301
  1. Run `rake build`
250
302
  1. Run `rake release`
251
303
  1. Change directories `cd ./javascript`
252
- 1. Run `yarn publish`
253
- 1. Assign same version number to the JavaScript package
254
- 1. Push changes to GitHub
255
- 1. Push tags to GitHub
256
-
257
- ```
258
- git push --tags
259
- ```
304
+ 1. Run `yarn publish --tag GIT_TAG_CREATED_BY_RUBYGEMS`
305
+ 1. Assign same version number to the JavaScript package _Might not be required?_
@@ -10,7 +10,7 @@ require "nokogiri"
10
10
  require "cable_ready"
11
11
  require "stimulus_reflex/version"
12
12
  require "stimulus_reflex/reflex"
13
- require "stimulus_reflex/dom_element"
13
+ require "stimulus_reflex/element"
14
14
  require "stimulus_reflex/channel"
15
15
 
16
16
  module StimulusReflex
@@ -22,11 +22,11 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
22
22
  reflex_name, method_name = target.split("#")
23
23
  reflex_name = reflex_name.classify
24
24
  arguments = data["args"] || []
25
- options = StimulusReflex::DomElement.new(data["attrs"])
25
+ element = StimulusReflex::Element.new(data["attrs"])
26
26
 
27
27
  begin
28
- reflex = reflex_name.constantize.new(self, url: url)
29
- delegate_call_to_reflex reflex, method_name, arguments, options
28
+ reflex = reflex_name.constantize.new(self, url: url, element: element)
29
+ delegate_call_to_reflex reflex, method_name, arguments
30
30
  rescue => invoke_error
31
31
  logger.error "\e[31mStimulusReflex::Channel Failed to invoke #{target}! #{url} #{invoke_error}\e[0m"
32
32
  end
@@ -40,24 +40,15 @@ class StimulusReflex::Channel < ActionCable::Channel::Base
40
40
 
41
41
  private
42
42
 
43
- def delegate_call_to_reflex(reflex, method_name, arguments = [], options = {})
43
+ def delegate_call_to_reflex(reflex, method_name, arguments = [])
44
44
  method = reflex.method(method_name)
45
45
  required_params = method.parameters.select { |(kind, _)| kind == :req }
46
46
  optional_params = method.parameters.select { |(kind, _)| kind == :opt }
47
- accepts_options_kwarg = method.parameters.select { |(kind, name)| name == :options && kind.to_s.start_with?("key") }.size > 0
48
47
 
49
48
  if arguments.size == 0 && required_params.size == 0
50
- if accepts_options_kwarg
51
- reflex.public_send method_name, {options: options}
52
- else
53
- reflex.public_send method_name
54
- end
49
+ reflex.public_send method_name
55
50
  elsif arguments.size >= required_params.size && arguments.size <= required_params.size + optional_params.size
56
- if accepts_options_kwarg
57
- reflex.public_send method_name, *arguments, {options: options}
58
- else
59
- reflex.public_send method_name, *arguments
60
- end
51
+ reflex.public_send method_name, *arguments
61
52
  else
62
53
  raise ArgumentError.new("wrong number of arguments (given #{arguments.inspect}, expected #{required_params.inspect}, optional #{optional_params.inspect})")
63
54
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class StimulusReflex::DomElement
3
+ class StimulusReflex::Element
4
4
  attr_reader :attributes
5
5
 
6
6
  delegate :[], to: :"@attributes"
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class StimulusReflex::Reflex
4
- attr_reader :channel, :url
4
+ attr_reader :channel, :url, :element
5
5
 
6
6
  delegate :connection, to: :channel
7
7
  delegate :session, to: :request
8
8
 
9
- def initialize(channel, url: nil)
9
+ def initialize(channel, url: nil, element: nil)
10
10
  @channel = channel
11
11
  @url = url
12
+ @element = element
12
13
  end
13
14
 
14
15
  def request
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StimulusReflex
4
- VERSION = "1.1.1"
4
+ VERSION = "2.0.0"
5
5
  end
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.1.1
4
+ version: 2.0.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: 2019-09-09 00:00:00.000000000 Z
12
+ date: 2019-09-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -156,7 +156,7 @@ files:
156
156
  - bin/standardize
157
157
  - lib/stimulus_reflex.rb
158
158
  - lib/stimulus_reflex/channel.rb
159
- - lib/stimulus_reflex/dom_element.rb
159
+ - lib/stimulus_reflex/element.rb
160
160
  - lib/stimulus_reflex/reflex.rb
161
161
  - lib/stimulus_reflex/version.rb
162
162
  homepage: https://github.com/hopsoft/stimulus_reflex