view_component_reflex 2.6.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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: []