phlex-reactive 0.4.0 → 0.4.1

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: 8811ee6a3c0f044fd7c9d16843a641296b33b8fcb5872f5bc8822257f837148e
4
- data.tar.gz: 9398a1c088680e83b8bed3398342345ceb817703183df0985a1948e29df021cf
3
+ metadata.gz: 786d397de0be7e32424c73079906cdf8d32d0325727d06027025d888693754e6
4
+ data.tar.gz: b080f12ff8c8f4271066993548f9c951278fe2dacabf9b7d21c2113704f58da4
5
5
  SHA512:
6
- metadata.gz: b17a5d83f62e801d0f8673f824f929a82d1c7efc2d0aa2274034639ed94b2c8c4723f11484427f051c7be15d523a0b99cd11594bed0d701e4ff2e07604a1edd8
7
- data.tar.gz: b5990726c0531bd2d6bc2da23df8bb2dbf5220ee702306c86f8094690da8c4a1752fa8ffb7949261050858256e5fd70854491603ac2306221c9f7bf2078f943c
6
+ metadata.gz: 316b9b2094490dd5045d1362276a8f31ba4deee96df08e6614dc9db8f62a2ceb822f5a474d2204dcb65f7ed1bb27b3c99303f14a180a336c2d5bc3d21c3bf31a
7
+ data.tar.gz: f54ecfe74e977b3d4a399cd004071792a3a7245636d1c82f19441b0240fb2d24d32bb072a3ae863a9e04efcab5a31182560628237f72bf77ff73ac387592e4c4
data/CHANGELOG.md CHANGED
@@ -72,6 +72,27 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
72
72
 
73
73
  ### Fixed
74
74
 
75
+ - **0.4.0 regression: re-renders lost the `request`, crashing `form_authenticity_token`
76
+ and other request-dependent helpers (#42).** The 0.4.0 render-path perf rework
77
+ built the cached off-request view context from a bare
78
+ `ActionController::Base.new.view_context`, whose controller has `request == nil`.
79
+ Any reactive component whose `view_template` calls `form_authenticity_token`,
80
+ `protect_against_forgery?`, or a host-aware URL helper (all of which read
81
+ `request.env`) then raised `NoMethodError: undefined method 'env' for nil` on
82
+ **every** re-render — through the action endpoint AND on broadcasts — so any app
83
+ with a reactive component rendering a Rails CSRF form could not adopt 0.4.0. Fixed
84
+ by building the cached view context through a request-bound controller
85
+ (`Phlex::Reactive.request_bound_view_context`), replicating exactly what
86
+ `ActionController::Renderer#render` does to set up its mock request: an
87
+ `ActionDispatch::Request` whose host is derived from the routes'
88
+ `default_url_options`. The 0.4.0 `render_in` speedup is kept — the request is set
89
+ up once when the per-thread context is built (not per render), and steady-state
90
+ render throughput/allocations are unchanged (retained-per-render stays 0). Covered
91
+ at the request level (a reactive `save` re-rendering a CSRF form returns 200, not
92
+ 500), the broadcast level (the form component broadcasts without crashing), and the
93
+ unit level (a request is present on the cached context; host-aware `*_url` helpers
94
+ resolve when the renderer carries routes).
95
+
75
96
  - **Multipart path silently dropped an explicit nested-hash / array param (#39).**
76
97
  When an action declared a `:file` param alongside an explicit nested (hash/array)
77
98
  param, the nested param was dropped on the multipart path while the JSON path
@@ -83,7 +83,10 @@ module Phlex
83
83
 
84
84
  # Turbo::Streams::TagBuilder needs a real VIEW CONTEXT (it calls
85
85
  # `.formats` on it), not a controller class. Build one off-request from
86
- # the configured renderer controller. Memoized PER THREAD building a
86
+ # the configured renderer controller, bound to a real request so
87
+ # request-dependent helpers (form_authenticity_token, host-aware URL
88
+ # helpers) work during a re-render/broadcast (issue #42). Memoized PER
89
+ # THREAD — building a
87
90
  # view context instantiates the renderer controller and assembles its
88
91
  # whole helper module set, so doing it per render/broadcast was the
89
92
  # hottest server-side allocation in the action round trip. The builder
@@ -260,7 +263,7 @@ module Phlex
260
263
  cached = store[self]
261
264
 
262
265
  unless cached && cached.renderer.equal?(current) && cached.generation == generation
263
- view_context = current.new.view_context
266
+ view_context = Phlex::Reactive.request_bound_view_context(current)
264
267
  cached = ThreadViewContext.new(
265
268
  view_context,
266
269
  ::Turbo::Streams::TagBuilder.new(view_context),
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlex
4
4
  module Reactive
5
- VERSION = "0.4.0"
5
+ VERSION = "0.4.1"
6
6
  end
7
7
  end
@@ -78,6 +78,30 @@ module Phlex
78
78
  @renderer ||= defined?(::ActionController::Base) ? ::ActionController::Base : nil
79
79
  end
80
80
 
81
+ # Build an off-request view context whose controller has a REAL `request`.
82
+ #
83
+ # A bare `controller.new.view_context` (the naive off-request context) has
84
+ # `request == nil`, so any request-dependent helper raises
85
+ # `undefined method 'env' for nil` — form_authenticity_token,
86
+ # protect_against_forgery?, and host-aware URL helpers all read
87
+ # `request.env` (issue #42). We replicate exactly what
88
+ # ActionController::Renderer#render does to set up its mock request — build
89
+ # an ActionDispatch::Request from the renderer's env (which derives the host
90
+ # from the routes' default_url_options), bind the routes, and attach it —
91
+ # then return the controller's view context instead of rendering a template.
92
+ # The result keeps the 0.4.0 render_in speedup (no renderer.render
93
+ # machinery) while restoring the request those helpers need.
94
+ def request_bound_view_context(controller_class)
95
+ ar_renderer = controller_class.renderer
96
+ request = ::ActionDispatch::Request.new(ar_renderer.send(:env_for_request))
97
+ request.routes = controller_class._routes
98
+
99
+ instance = controller_class.new
100
+ instance.set_request!(request)
101
+ instance.set_response!(controller_class.make_response!(request))
102
+ instance.view_context
103
+ end
104
+
81
105
  # DOM id of the host-app container a Response#flash appends into.
82
106
  # Default "flash"; override to match your layout's flash region.
83
107
  def flash_target
@@ -136,7 +160,7 @@ module Phlex
136
160
  generation = off_request_view_context_generation
137
161
 
138
162
  unless cache && cache[:renderer].equal?(current) && cache[:generation] == generation
139
- view_context = current.new.view_context
163
+ view_context = request_bound_view_context(current)
140
164
  cache = {
141
165
  view_context: view_context,
142
166
  builder: ::Turbo::Streams::TagBuilder.new(view_context),
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex-reactive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson