Skip to content

Commit 2a86210

Browse files
committed
feat(RenderMiddleware) use middleware for view helper lifecycle
1 parent 3c1152a commit 2a86210

File tree

5 files changed

+63
-2
lines changed

5 files changed

+63
-2
lines changed

lib/react/rails.rb

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require 'react/rails/asset_variant'
22
require 'react/rails/engine'
33
require 'react/rails/railtie'
4+
require 'react/rails/render_middleware'
45
require 'react/rails/version'
56
require 'react/rails/component_mount'
67
require 'react/rails/view_helper'

lib/react/rails/railtie.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ module React
44
module Rails
55
class Railtie < ::Rails::Railtie
66
config.react = ActiveSupport::OrderedOptions.new
7-
87
# Sensible defaults. Can be overridden in application.rb
98
config.react.variant = (::Rails.env.production? ? :production : :development)
109
config.react.addons = false
@@ -25,6 +24,7 @@ class Railtie < ::Rails::Railtie
2524

2625
# Include the react-rails view helper lazily
2726
initializer "react_rails.setup_view_helpers", group: :all do |app|
27+
app.config.middleware.use(::React::Rails::RenderMiddleware)
2828
app.config.react.jsx_transformer_class ||= React::JSX::DEFAULT_TRANSFORMER
2929
React::JSX.transformer_class = app.config.react.jsx_transformer_class
3030
React::JSX.transform_options = app.config.react.jsx_transform_options

lib/react/rails/render_middleware.rb

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module React
2+
module Rails
3+
class RenderMiddleware
4+
HELPER_IMPLEMENTATION_KEY = "react_rails.view_helper_implementation"
5+
def initialize(app)
6+
@app = app
7+
end
8+
9+
def call(env)
10+
new_helper = React::Rails::ViewHelper.helper_implementation_class.new
11+
env[HELPER_IMPLEMENTATION_KEY] = new_helper
12+
@app.call(env)
13+
end
14+
end
15+
end
16+
end

lib/react/rails/view_helper.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ module ViewHelper
77
mattr_accessor :helper_implementation_class
88

99
def react_component(*args, &block)
10-
self.helper_implementation_class.new.react_component(*args, &block)
10+
impl_key = React::Rails::RenderMiddleware::HELPER_IMPLEMENTATION_KEY
11+
helper_obj = request.env[impl_key]
12+
helper_obj.react_component(*args, &block)
1113
end
1214
end
1315
end
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require 'test_helper'
2+
3+
# This helper implementation just counts the number of
4+
# calls to `react_component`
5+
class DummyHelperImplementation
6+
attr_reader :counter
7+
def initialize
8+
@counter = 0
9+
end
10+
11+
def react_component(*args)
12+
@counter += 1
13+
end
14+
end
15+
16+
class RenderMiddlewareTest < ActionDispatch::IntegrationTest
17+
impl_key = React::Rails::RenderMiddleware::HELPER_IMPLEMENTATION_KEY
18+
19+
def setup
20+
@previous_helper_implementation = React::Rails::ViewHelper.helper_implementation_class
21+
React::Rails::ViewHelper.helper_implementation_class = DummyHelperImplementation
22+
end
23+
24+
def teardown
25+
React::Rails::ViewHelper.helper_implementation_class = @previous_helper_implementation
26+
end
27+
28+
test "it creates a helper object and puts it in the request env" do
29+
get '/pages/1'
30+
helper_obj = request.env[impl_key]
31+
assert(helper_obj.is_a?(DummyHelperImplementation), "It uses the view helper implementation class")
32+
assert_equal(1, helper_obj.counter, "It uses that object during rendering")
33+
end
34+
35+
test "there's a new helper object for every request" do
36+
get '/pages/1'
37+
first_helper = request.env[impl_key]
38+
get '/pages/1'
39+
second_helper = request.env[impl_key]
40+
assert(first_helper != second_helper, "The helper for the second request is brand new")
41+
end
42+
end

0 commit comments

Comments
 (0)