view_component_reflex 2.3.10 → 2.6.0

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: 1dad0cc0f7e6d5012a4ccc2d4bce92eb1d50f2d8c47bb803fabcbd7abb9fa28e
4
- data.tar.gz: f448c90389a5c07addca133a0a046ca142b32db08e9e19b17d428dcf08d3b2db
3
+ metadata.gz: 48be01529611392c673d2ca154ba25657bde6564cfb9238c78debea251f3aa11
4
+ data.tar.gz: 41d40953951fbd6d26fa4044ad41e1ca6b5b2a969439404d78f755853ea1acca
5
5
  SHA512:
6
- metadata.gz: 0ce1685cc918835c629aaca35d30e0b3492fa27776126bfe4a01d8e65d711c9fd6617d816ed62c7abd5d718e87c33e8da25aaed64b8511050bdd11c4d3bbfece
7
- data.tar.gz: a4369503902bc85b1fd9105f678d0a27f6199aeec232d386126179fd064e0796605d3eab0b4932bbec81b002fb025fa065ad6863275aceadb66536ad964d9355
6
+ metadata.gz: a6b645acacb1f3716b05cf134225255096aa80ef47a131949d79f0cbfec69a9623c6f26d061d381f6637ff26501eeaeabdfe17c52e7cb2be027eda0e5eba91ec
7
+ data.tar.gz: 9d714a2889b6d4f100cd816f6068699e86966807bf529353b9ab2699738d649a5169116926e75fd5690a2cbb7a0583574cf164b52518b4cff29e86745a38d803
data/README.md CHANGED
@@ -161,7 +161,7 @@ By default, VCR will re-render your component after it executes your method. `pr
161
161
  ```ruby
162
162
  def my_method
163
163
  prevent_refresh!
164
- @foo = Lbar
164
+ @foo = :bar
165
165
  end # the rendered page will not reflect this change
166
166
  ```
167
167
 
@@ -193,6 +193,19 @@ You *must* wrap your component in this for everything to work properly.
193
193
  <% end %>
194
194
  ```
195
195
 
196
+ ### after_state_initialized(parameters_changed)
197
+
198
+ This is called after the state has been inserted in the component. You can use this to run conditional functions after
199
+ some parameter has superseeded whatever's in state
200
+
201
+ ```
202
+ def after_state_initialized(parameters_changed)
203
+ if parameters_changed.include?(:@filter)
204
+ calculate_visible_rows
205
+ end
206
+ end
207
+ ```
208
+
196
209
  ## Custom reflex base class
197
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.
198
211
  The parent class must inherit ViewComponentReflex::Reflex, and will throw an error if it does not.
@@ -245,8 +258,8 @@ end
245
258
 
246
259
  ## State
247
260
 
248
- By default, view_component_reflex stores component state in memory. You can optionally set the state adapter
249
- to use the session by changing `config.state_adapter` to `ViewComponentReflex::StateAdapter::Session`
261
+ By default (since version `2.3.2`), view_component_reflex stores component state in session. You can optionally set the state adapter
262
+ to use the memory by changing `config.state_adapter` to `ViewComponentReflex::StateAdapter::Memory`.
250
263
 
251
264
  ## Custom State Adapters
252
265
 
@@ -259,6 +272,22 @@ ViewComponentReflex::Engine.configure do |config|
259
272
  end
260
273
  ```
261
274
 
275
+
276
+ ## Existing Fast Redis based State Adapter
277
+
278
+ This adapter uses hmset and hgetall to reduce the number of operations.
279
+ This is the recommended adapter if you are using AnyCable.
280
+
281
+ ```ruby
282
+ ViewComponentReflex::Engine.configure do |config|
283
+ config.state_adapter = ViewComponentReflex::StateAdapter::Redis.new(
284
+ redis_opts: {
285
+ url: "redis://localhost:6379/1", driver: :hiredis
286
+ },
287
+ ttl: 3600)
288
+ end
289
+ ```
290
+
262
291
  `YourAdapter` should implement
263
292
 
264
293
  ```ruby
@@ -139,33 +139,46 @@ module ViewComponentReflex
139
139
  []
140
140
  end
141
141
 
142
+ def after_state_initialized(parameters_changed)
143
+ # called after state component has been hydrated
144
+ end
145
+
142
146
  # def receive_params(old_state, params)
143
147
  # # no op
144
148
  # end
145
149
 
146
150
  def key
151
+ adapter = ViewComponentReflex::Engine.state_adapter
152
+
147
153
  # initialize session state
148
- if !stimulus_reflex? || ViewComponentReflex::Engine.state_adapter.state(request, @key).empty?
154
+ if !stimulus_reflex? || adapter.state(request, @key).empty?
149
155
 
150
156
  new_state = create_safe_state
151
157
 
152
- ViewComponentReflex::Engine.state_adapter.store_state(request, @key, new_state)
153
- ViewComponentReflex::Engine.state_adapter.store_state(request, "#{@key}_initial", new_state)
158
+ adapter.wrap_write_async do
159
+ adapter.store_state(request, @key, new_state)
160
+ adapter.store_state(request, "#{@key}_initial", new_state)
161
+ end
154
162
  elsif !@initialized_state
155
- initial_state = ViewComponentReflex::Engine.state_adapter.state(request, "#{@key}_initial")
163
+ initial_state = adapter.state(request, "#{@key}_initial")
156
164
 
157
165
  # incoming_params = safe_instance_variables.each_with_object({}) { |var, obj| obj[var] = instance_variable_get(var) }
158
166
  # receive_params(ViewComponentReflex::Engine.state_adapter.state(request, @key), incoming_params)
159
167
 
160
- ViewComponentReflex::Engine.state_adapter.state(request, @key).each do |k, v|
168
+ parameters_changed = []
169
+ adapter.state(request, @key).each do |k, v|
161
170
  instance_value = instance_variable_get(k)
162
171
  if permit_parameter?(initial_state[k], instance_value)
163
- ViewComponentReflex::Engine.state_adapter.set_state(request, controller, "#{@key}_initial", {k => instance_value})
164
- ViewComponentReflex::Engine.state_adapter.set_state(request, controller, @key, {k => instance_value})
172
+ parameters_changed << k
173
+ adapter.wrap_write_async do
174
+ adapter.set_state(request, controller, "#{@key}_initial", {k => instance_value})
175
+ adapter.set_state(request, controller, @key, {k => instance_value})
176
+ end
165
177
  else
166
178
  instance_variable_set(k, v)
167
179
  end
168
180
  end
181
+ after_state_initialized(parameters_changed)
169
182
  @initialized_state = true
170
183
  end
171
184
  @key
@@ -2,6 +2,7 @@ require "stimulus_reflex"
2
2
  require 'view_component_reflex/reflex_factory'
3
3
  require "view_component_reflex/state_adapter/session"
4
4
  require "view_component_reflex/state_adapter/memory"
5
+ require "view_component_reflex/state_adapter/redis"
5
6
  require "view_component_reflex/reflex"
6
7
  require "view_component_reflex/engine"
7
8
 
@@ -119,7 +119,7 @@ module ViewComponentReflex
119
119
  return @component if @component
120
120
  @component = component_class.allocate
121
121
  reflex = self
122
- exposed_methods = [:params, :request, :element, :refresh!, :refresh_all!, :stimulus_controller, :session, :prevent_refresh!, :selector, :stimulate]
122
+ exposed_methods = [:params, :request, :connection, :element, :refresh!, :refresh_all!, :stimulus_controller, :session, :prevent_refresh!, :selector, :stimulate]
123
123
  exposed_methods.each do |meth|
124
124
  @component.define_singleton_method(meth) do |*a|
125
125
  reflex.send(meth, *a)
@@ -20,6 +20,10 @@ module ViewComponentReflex
20
20
  VIEW_COMPONENT_REFLEX_MEMORY_STATE[request.session.id.to_s][key][k] = v
21
21
  end
22
22
  end
23
+
24
+ def self.wrap_write_async
25
+ yield
26
+ end
23
27
  end
24
28
  end
25
29
  end
@@ -0,0 +1,74 @@
1
+ # A redis based adapter for component_reflex
2
+ #
3
+ # ViewComponentReflex::Engine.configure do |config|
4
+ # config.state_adapter = ViewComponentReflex::StateAdapter::Redis.new(
5
+ # redis_opts: {
6
+ # url: "redis://localhost:6379/1", driver: :hiredis
7
+ # },
8
+ # ttl: 3600)
9
+ # end
10
+
11
+ module ViewComponentReflex
12
+ module StateAdapter
13
+ class Redis
14
+ attr_reader :client, :ttl
15
+
16
+ def initialize(redis_opts:, ttl: 3600)
17
+ @client = ::Redis.new(redis_opts)
18
+ @ttl = ttl
19
+ end
20
+
21
+ def state(request, key)
22
+ cache_key = get_key(request, key)
23
+ value = client.hgetall(cache_key)
24
+
25
+ return {} if value.nil?
26
+
27
+ value.map do |k, v|
28
+ [k, Marshal.load(v)]
29
+ end.to_h
30
+ end
31
+
32
+ def set_state(request, _, key, new_state)
33
+ cache_key = get_key(request, key)
34
+ save_to_redis(cache_key, new_state)
35
+ end
36
+
37
+ def store_state(request, key, new_state = {})
38
+ cache_key = get_key(request, key)
39
+ optimized_store_to_redis(cache_key, new_state, request)
40
+ end
41
+
42
+ def wrap_write_async
43
+ client.pipelined do
44
+ yield
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # Reduce number of calls coming from #store_state to save Redis
51
+ # when it's first rendered
52
+ def optimized_store_to_redis(cache_key, new_state, request)
53
+ request.env["CACHE_REDIS_REFLEX"] ||= []
54
+ return if request.env["CACHE_REDIS_REFLEX"].include?(cache_key)
55
+ request.env["CACHE_REDIS_REFLEX"].push(cache_key)
56
+
57
+ save_to_redis(cache_key, new_state)
58
+ end
59
+
60
+ def save_to_redis(cache_key, new_state)
61
+ new_state_json = new_state.map do |k, v|
62
+ [k, Marshal.dump(v)]
63
+ end
64
+
65
+ client.hmset(cache_key, new_state_json.flatten)
66
+ client.expire(cache_key, ttl)
67
+ end
68
+
69
+ def get_key(request, key)
70
+ "#{request.session.id.to_s}_#{key}_session_reflex_redis"
71
+ end
72
+ end
73
+ end
74
+ end
@@ -19,6 +19,10 @@ module ViewComponentReflex
19
19
  request.session[key][k] = v
20
20
  end
21
21
  end
22
+
23
+ def self.wrap_write_async
24
+ yield
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -1,3 +1,3 @@
1
1
  module ViewComponentReflex
2
- VERSION = '2.3.10'
2
+ VERSION = '2.6.0'
3
3
  end
metadata CHANGED
@@ -1,35 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: view_component_reflex
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.10
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua LeBlanc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-07 00:00:00.000000000 Z
11
+ date: 2020-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 6.0.3
20
17
  - - ">="
21
18
  - !ruby/object:Gem::Version
22
- version: 6.0.3.1
19
+ version: '5.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: 6.0.3
30
27
  - - ">="
31
28
  - !ruby/object:Gem::Version
32
- version: 6.0.3.1
29
+ version: '5.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7.0'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: stimulus_reflex
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -74,6 +74,7 @@ files:
74
74
  - lib/view_component_reflex/reflex.rb
75
75
  - lib/view_component_reflex/reflex_factory.rb
76
76
  - lib/view_component_reflex/state_adapter/memory.rb
77
+ - lib/view_component_reflex/state_adapter/redis.rb
77
78
  - lib/view_component_reflex/state_adapter/session.rb
78
79
  - lib/view_component_reflex/version.rb
79
80
  homepage: https://github.com/joshleblanc/view_component_reflex