view_component_reflex 2.6.0 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48be01529611392c673d2ca154ba25657bde6564cfb9238c78debea251f3aa11
4
- data.tar.gz: 41d40953951fbd6d26fa4044ad41e1ca6b5b2a969439404d78f755853ea1acca
3
+ metadata.gz: 9df2379bc1c256d8d3b703c542693300fd82af260540d819174e1ac77b98a42e
4
+ data.tar.gz: 3918c1cbe4ef273c94583d65373a8a574971607e825769040a410282aed3558f
5
5
  SHA512:
6
- metadata.gz: a6b645acacb1f3716b05cf134225255096aa80ef47a131949d79f0cbfec69a9623c6f26d061d381f6637ff26501eeaeabdfe17c52e7cb2be027eda0e5eba91ec
7
- data.tar.gz: 9d714a2889b6d4f100cd816f6068699e86966807bf529353b9ab2699738d649a5169116926e75fd5690a2cbb7a0583574cf164b52518b4cff29e86745a38d803
6
+ metadata.gz: c1c741bf5d6005a7cc8b9c48bf428b2920234872a7c5b2b186052c579f33448a5366f95d596e93e82e314d39dfe44086ae654d1aacb000ad764aabb5fc870a20
7
+ data.tar.gz: 189253b1a19210ab6dfc550408300169bdd43b6ce42b69165286af86ee1bf1bff278c9bc65c97ee5d8513af946f68bcae10bd1ba67ea5f4bf0785e8d5db456c3
@@ -1,20 +1,20 @@
1
- Copyright 2020 Joshua LeBlanc
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright 2020 Joshua LeBlanc
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -6,7 +6,7 @@ It builds upon [stimulus_reflex](https://github.com/hopsoft/stimulus_reflex) and
6
6
 
7
7
  ## Usage
8
8
 
9
- You can add reflexes to your component by adding inheriting from `ViewComponentReflex::Component`.
9
+ You can add reflexes to your component by inheriting from `ViewComponentReflex::Component`.
10
10
 
11
11
  This will act as if you created a reflex with the method `my_cool_stuff`. To call this reflex, add `data-reflex="click->MyComponentReflex#my_cool_reflex"`, just like you're
12
12
  using stimulus reflex.
@@ -124,7 +124,7 @@ def initialize
124
124
  end
125
125
 
126
126
  def collection_key
127
- @my_model.id
127
+ @my_model.id
128
128
  end
129
129
  ```
130
130
 
@@ -207,7 +207,7 @@ end
207
207
  ```
208
208
 
209
209
  ## Custom reflex base class
210
- Reflexes typically inherit from a base ApplicationReflex. You can define the base class for a view_component_reflex by using the `reflex_base_class` method.
210
+ Reflexes typically inherit from a base ApplicationReflex. You can define the base class for a view_component_reflex by using the `reflex_base_class` accessor.
211
211
  The parent class must inherit ViewComponentReflex::Reflex, and will throw an error if it does not.
212
212
 
213
213
  ```ruby
@@ -217,7 +217,7 @@ end
217
217
 
218
218
 
219
219
  class MyComponent < ViewComponentReflex::Component
220
- reflex_base_class ApplicationReflex
220
+ MyComponent.reflex_base_class = ApplicationReflex
221
221
  end
222
222
  ```
223
223
 
@@ -348,6 +348,46 @@ $ gem install view_component_reflex
348
348
  ## Uninitialized constants \<component\>Reflex
349
349
  A component needs to be wrapped in `<%= component_controller do %>` in order to properly initialize, otherwise the Reflex class won't get created.
350
350
 
351
+ ## Session is an empty hash
352
+ StimulusReflex 3.3 introduced _selector morphs_, allowing you to render arbitrary strings via `ApplicationController.render`, for example:
353
+
354
+ ```rb
355
+ def test_selector
356
+ morph '#some-container', ApplicationController.render(MyComponent.new(some: :param))
357
+ end
358
+ ```
359
+
360
+ StimulusReflex 3.4 introduced a fix that merges the current `request.env` and provides the CSRF token to fetch the session.
361
+
362
+ ## Help, my instance variables do not persist into the session
363
+
364
+ These instance variable names are not working and unsafe:
365
+
366
+ ```rb
367
+ def unsafe_instance_variables
368
+ [
369
+ :@view_context, :@lookup_context, :@view_renderer, :@view_flow,
370
+ :@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
371
+ :@helpers, :@controller, :@request, :@tag_builder, :@initialized_state
372
+ ]
373
+ end
374
+ ```
375
+ Please use a different name to be able to save them to the session.
376
+
377
+ ## Anycable
378
+
379
+ @sebyx07 provided a solution to use anycable (https://github.com/joshleblanc/view_component_reflex/issues/23#issue-721786338)
380
+
381
+ Leaving this, might help others:
382
+
383
+ I tried this with any cable and I had to add this to development.rb
384
+ Otherwise @instance_variables were nil after a reflex
385
+
386
+ ```ruby
387
+ config.cache_store = :redis_cache_store, { url: "redis://localhost:6379/1", driver: :hiredis }
388
+ config.session_store :cache_store
389
+ ```
390
+
351
391
  ## License
352
392
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
353
393
 
data/Rakefile CHANGED
@@ -1,32 +1,32 @@
1
- begin
2
- require 'bundler/setup'
3
- rescue LoadError
4
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
- end
6
-
7
- require 'rdoc/task'
8
-
9
- RDoc::Task.new(:rdoc) do |rdoc|
10
- rdoc.rdoc_dir = 'rdoc'
11
- rdoc.title = 'ViewComponentReflex'
12
- rdoc.options << '--line-numbers'
13
- rdoc.rdoc_files.include('README.md')
14
- rdoc.rdoc_files.include('lib/**/*.rb')
15
- end
16
-
17
- APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
- load 'rails/tasks/engine.rake'
19
-
20
- load 'rails/tasks/statistics.rake'
21
-
22
- require 'bundler/gem_tasks'
23
-
24
- require 'rake/testtask'
25
-
26
- Rake::TestTask.new(:test) do |t|
27
- t.libs << 'test'
28
- t.pattern = 'test/**/*_test.rb'
29
- t.verbose = false
30
- end
31
-
32
- task default: :test
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'ViewComponentReflex'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
@@ -1,5 +1,7 @@
1
1
  module ViewComponentReflex
2
2
  class Component < ViewComponent::Base
3
+ class_attribute :reflex_base_class, default: ViewComponentReflex::Reflex
4
+
3
5
  class << self
4
6
  def init_stimulus_reflex
5
7
  factory = ViewComponentReflex::ReflexFactory.new(self)
@@ -7,18 +9,6 @@ module ViewComponentReflex
7
9
  wire_up_callbacks if factory.new?
8
10
  end
9
11
 
10
- def reflex_base_class(new_base_class = nil)
11
- if new_base_class.nil?
12
- @reflex_base_class ||= ViewComponentReflex::Reflex
13
- else
14
- if new_base_class <= ViewComponentReflex::Reflex
15
- @reflex_base_class = new_base_class
16
- else
17
- raise StandardError.new("The reflex base class must inherit from ViewComponentReflex::Reflex")
18
- end
19
- end
20
- end
21
-
22
12
  def queue_callback(key, args, blk)
23
13
  callbacks(key).push({
24
14
  args: args,
@@ -151,7 +141,7 @@ module ViewComponentReflex
151
141
  adapter = ViewComponentReflex::Engine.state_adapter
152
142
 
153
143
  # initialize session state
154
- if !stimulus_reflex? || adapter.state(request, @key).empty?
144
+ if (!stimulus_reflex? || adapter.state(request, @key).empty?) && !@initialized_state
155
145
 
156
146
  new_state = create_safe_state
157
147
 
@@ -179,13 +169,14 @@ module ViewComponentReflex
179
169
  end
180
170
  end
181
171
  after_state_initialized(parameters_changed)
182
- @initialized_state = true
183
172
  end
173
+
174
+ @initialized_state = true
184
175
  @key
185
176
  end
186
177
 
187
178
  def safe_instance_variables
188
- instance_variables - unsafe_instance_variables
179
+ instance_variables - unsafe_instance_variables - omitted_from_state
189
180
  end
190
181
 
191
182
  private
@@ -203,7 +194,7 @@ module ViewComponentReflex
203
194
 
204
195
  # this will almost certainly break
205
196
  safe_instance_variables.each do |k|
206
- new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
197
+ new_state[k] = instance_variable_get(k)
207
198
  end
208
199
  new_state
209
200
  end
@@ -1,10 +1,8 @@
1
1
  module ViewComponentReflex
2
2
  class Engine < ::Rails::Engine
3
- class << self
4
- mattr_accessor :state_adapter
5
3
 
6
- self.state_adapter = StateAdapter::Session
7
- end
4
+ mattr_accessor :state_adapter
5
+ Engine.state_adapter = StateAdapter::Session
8
6
 
9
7
  config.to_prepare do
10
8
  StimulusReflex::Channel.class_eval do
@@ -15,13 +13,16 @@ module ViewComponentReflex
15
13
  reflex_name, _ = target.split("#")
16
14
  reflex_name = reflex_name.camelize
17
15
  component_name = reflex_name.end_with?("Reflex") ? reflex_name[0...-6] : reflex_name
18
- if component_name.end_with?("Component")
19
- begin
20
- component_name.constantize.init_stimulus_reflex
21
- rescue
22
- p "Tried to initialize view_component_reflex on #{component_name}, but it's not a view_component_reflex"
23
- end
16
+ component = begin
17
+ component_name.constantize
18
+ rescue
19
+ # Since every reflex runs through this monkey patch, we're just going to ignore the ones that aren't for components
20
+ end
24
21
 
22
+ if component&.respond_to?(:init_stimulus_reflex)
23
+ component.init_stimulus_reflex
24
+ else
25
+ p "Tried to initialize view_component_reflex on #{component_name}, but it's not a view_component_reflex"
25
26
  end
26
27
  receive_original(data)
27
28
  end
@@ -1,6 +1,5 @@
1
1
  module ViewComponentReflex
2
2
  class Reflex < StimulusReflex::Reflex
3
- include CableReady::Broadcaster
4
3
 
5
4
  class << self
6
5
  attr_accessor :component_class
@@ -15,16 +14,26 @@ module ViewComponentReflex
15
14
  if primary_selector
16
15
  prevent_refresh!
17
16
 
18
- controller.process(url_params[:action])
17
+ controller.process(params[:action])
19
18
  document = Nokogiri::HTML(controller.response.body)
20
19
  [primary_selector, *rest].each do |s|
21
20
  html = document.css(s)
22
21
  if html.present?
23
- cable_ready[channel.stream_name].morph(
22
+ CableReady::Channels.instance[stream_name].morph(
24
23
  selector: s,
25
24
  html: html.inner_html,
26
25
  children_only: true,
27
- permanent_attribute_name: "data-reflex-permanent"
26
+ permanent_attribute_name: "data-reflex-permanent",
27
+ stimulus_reflex: {
28
+ reflex_id: reflex_id,
29
+ xpath: xpath,
30
+ c_xpath: c_xpath,
31
+ target: target,
32
+ reflex_controller: reflex_controller,
33
+ url: url,
34
+ morph: :page,
35
+ attrs: {key: element.dataset[:key]}
36
+ }
28
37
  )
29
38
  end
30
39
  end
@@ -40,15 +49,29 @@ module ViewComponentReflex
40
49
  element.dataset[:key]
41
50
  end
42
51
  end
43
- document = Nokogiri::HTML(controller.render_component_to_string(component))
44
- cable_ready[channel.stream_name].morph(
52
+ document = Nokogiri::HTML(component.render_in(controller.view_context))
53
+ CableReady::Channels.instance[stream_name].morph(
45
54
  selector: selector,
46
55
  children_only: true,
47
56
  html: document.css(selector).inner_html,
48
- permanent_attribute_name: "data-reflex-permanent"
57
+ permanent_attribute_name: "data-reflex-permanent",
58
+ stimulus_reflex: {
59
+ reflex_id: reflex_id,
60
+ xpath: xpath,
61
+ target: target,
62
+ c_xpath: c_xpath,
63
+ reflex_controller: reflex_controller,
64
+ url: url,
65
+ morph: :page,
66
+ attrs: {key: element.dataset[:key]}
67
+ }
49
68
  )
50
69
  end
51
70
 
71
+ def target
72
+ "#{component_class}##{method_name}"
73
+ end
74
+
52
75
  def refresh_all!
53
76
  refresh!("body")
54
77
  end
@@ -35,11 +35,17 @@ module ViewComponentReflex
35
35
  end
36
36
 
37
37
  def reflex_from_nested_component
38
- if @component.module_parent.const_defined?(reflex_name)
39
- @component.module_parent.const_get(reflex_name)
38
+ parent = if @component.respond_to? :module_parent
39
+ @component.module_parent
40
+ else
41
+ @component.parent
42
+ end
43
+
44
+ if parent.const_defined?(reflex_name)
45
+ parent.const_get(reflex_name)
40
46
  else
41
47
  @new = true
42
- @component.module_parent.const_set(reflex_name, reflex_instance)
48
+ parent.const_set(reflex_name, reflex_instance)
43
49
  end
44
50
  end
45
51
 
@@ -3,8 +3,10 @@ module ViewComponentReflex
3
3
  module StateAdapter
4
4
  class Memory
5
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] ||= {}
6
+ id = extract_id(request)
7
+
8
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id] ||= {}
9
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key] ||= {}
8
10
  end
9
11
 
10
12
  def self.set_state(request, _, key, new_state)
@@ -14,16 +16,29 @@ module ViewComponentReflex
14
16
  end
15
17
 
16
18
  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
+ id = extract_id(request)
20
+
21
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id] ||= {}
22
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key] = {}
19
23
  new_state.each do |k, v|
20
- VIEW_COMPONENT_REFLEX_MEMORY_STATE[request.session.id.to_s][key][k] = v
24
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key][k] = v
21
25
  end
22
26
  end
23
27
 
24
28
  def self.wrap_write_async
25
29
  yield
26
30
  end
31
+
32
+ private
33
+
34
+ def self.extract_id(request)
35
+ session = request&.session
36
+ if session.respond_to? :id
37
+ session.id.to_s
38
+ else
39
+ nil
40
+ end
41
+ end
27
42
  end
28
43
  end
29
44
  end
@@ -1,3 +1,3 @@
1
1
  module ViewComponentReflex
2
- VERSION = '2.6.0'
2
+ VERSION = '3.0.2'
3
3
  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: 2.6.0
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua LeBlanc
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-17 00:00:00.000000000 Z
11
+ date: 2020-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -34,16 +34,16 @@ dependencies:
34
34
  name: stimulus_reflex
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - "~>"
37
+ - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 3.3.0
39
+ version: 3.4.0.pre9
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - '='
45
45
  - !ruby/object:Gem::Version
46
- version: 3.3.0
46
+ version: 3.4.0.pre9
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: view_component
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -58,6 +58,20 @@ dependencies:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: sqlite3
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
61
75
  description: Allow stimulus reflexes in a view component
62
76
  email:
63
77
  - joshleblanc94@gmail.com
@@ -82,7 +96,7 @@ licenses:
82
96
  - MIT
83
97
  metadata:
84
98
  allowed_push_host: https://rubygems.org
85
- post_install_message:
99
+ post_install_message:
86
100
  rdoc_options: []
87
101
  require_paths:
88
102
  - lib
@@ -97,8 +111,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
111
  - !ruby/object:Gem::Version
98
112
  version: '0'
99
113
  requirements: []
100
- rubygems_version: 3.0.3
101
- signing_key:
114
+ rubygems_version: 3.1.4
115
+ signing_key:
102
116
  specification_version: 4
103
117
  summary: Allow stimulus reflexes in a view component
104
118
  test_files: []