react-rails 1.2.0 → 1.3.0
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 +4 -4
- data/README.md +69 -9
- data/lib/react/jsx.rb +1 -1
- data/lib/react/rails.rb +3 -0
- data/lib/react/rails/component_mount.rb +46 -0
- data/lib/react/rails/controller_renderer.rb +18 -0
- data/lib/react/rails/railtie.rb +15 -2
- data/lib/react/rails/render_middleware.rb +19 -0
- data/lib/react/rails/version.rb +1 -1
- data/lib/react/rails/view_helper.rb +11 -21
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcffb8326ddf9468f84991dc075b824339192aa6
|
4
|
+
data.tar.gz: 732958fbaa2b917816cc4febcd340e4d439ac397
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03572f213be4ef8de3be2a513fe56b8fe825f456e704271a785e2f8f9afbe8c0f12670809e441b0da1d1968bce0676db5d993333879dd9b6b126c4f32cf67680
|
7
|
+
data.tar.gz: 33c018c9e2dc905b5c3e505f75882344345e00ecfd8fb9a6aa4a8ee85468bd74a30fa44ca1b6a75105df06ae98c28c050f3b5c82d15d5aacd34a14b4c9c62640
|
data/README.md
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
# react-rails
|
10
10
|
|
11
11
|
|
12
|
-
`react-rails` makes it easy to use [React](http://facebook.github.io/react/) and [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html)
|
12
|
+
`react-rails` makes it easy to use [React](http://facebook.github.io/react/) and [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html)
|
13
13
|
in your Ruby on Rails (3.2+) application. `react-rails` can:
|
14
14
|
|
15
15
|
- Provide [various `react` builds](#reactjs-builds) to your asset bundle
|
@@ -17,13 +17,14 @@ in your Ruby on Rails (3.2+) application. `react-rails` can:
|
|
17
17
|
- [Render components into views and mount them](#rendering--mounting) via view helper & `react_ujs`
|
18
18
|
- [Render components server-side](#server-rendering) with `prerender: true`
|
19
19
|
- [Generate components](#component-generator) with a Rails generator
|
20
|
+
- [Be extended](#extending-react-rails) with custom renderers, transformers and view helpers
|
20
21
|
|
21
22
|
## Installation
|
22
23
|
|
23
24
|
Add `react-rails` to your gemfile:
|
24
25
|
|
25
26
|
```ruby
|
26
|
-
gem 'react-rails', '~> 1.0'
|
27
|
+
gem 'react-rails', '~> 1.3.0'
|
27
28
|
```
|
28
29
|
|
29
30
|
Next, run the installation script:
|
@@ -82,27 +83,31 @@ See [VERSIONS.md](https://github.com/reactjs/react-rails/blob/master/VERSIONS.md
|
|
82
83
|
After installing `react-rails`, restart your server. Now, `.js.jsx` files will be transformed in the asset pipeline.
|
83
84
|
|
84
85
|
`react-rails` currently ships with two transformers, to convert jsx code -
|
85
|
-
|
86
|
+
|
86
87
|
* `BabelTransformer` using [Babel](http://babeljs.io), which is the default transformer.
|
87
88
|
* `JSXTransformer` using `JSXTransformer.js`
|
88
89
|
|
90
|
+
You can use the deprecated `JSXTransformer` by setting it in an application config:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
config.react.jsx_transformer_class = React::JSX::JSXTransformer
|
94
|
+
```
|
95
|
+
|
89
96
|
#### BabelTransformer options
|
90
97
|
|
91
|
-
You can use babel's [transformers](http://babeljs.io/docs/advanced/transformers/) and [custom plugins](http://babeljs.io/docs/advanced/plugins/),
|
98
|
+
You can use babel's [transformers](http://babeljs.io/docs/advanced/transformers/) and [custom plugins](http://babeljs.io/docs/advanced/plugins/),
|
92
99
|
and pass [options](http://babeljs.io/docs/usage/options/) to the babel transpiler adding following configurations:
|
93
100
|
|
94
101
|
```ruby
|
95
102
|
config.react.jsx_transform_options = {
|
96
103
|
blacklist: ['spec.functionName', 'validation.react'], # default options
|
97
104
|
optional: ["transformerName"], # pass extra babel options
|
98
|
-
whitelist: ["useStrict"] # even more options
|
105
|
+
whitelist: ["useStrict"] # even more options
|
99
106
|
}
|
100
107
|
```
|
101
108
|
Under the hood, `react-rails` uses [ruby-babel-transpiler](https://github.com/babel/ruby-babel-transpiler), for transformation.
|
102
|
-
|
103
|
-
#### JSXTransformer options
|
104
109
|
|
105
|
-
|
110
|
+
#### JSXTransformer options
|
106
111
|
|
107
112
|
You can use JSX `--harmony` or `--strip-types` options by adding a configuration:
|
108
113
|
|
@@ -199,6 +204,22 @@ end
|
|
199
204
|
- On MRI, you'll get a deadlock with `pool_size` > 1
|
200
205
|
- If you're using JRuby, you can increase `pool_size` to have real multi-threaded rendering.
|
201
206
|
|
207
|
+
### Rendering components instead of views
|
208
|
+
|
209
|
+
Components can also be prerendered directly from a controller action with the custom `component` renderer. For example:
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
class TodoController < ApplicationController
|
213
|
+
def index
|
214
|
+
@todos = Todo.all
|
215
|
+
render component: 'TodoList', props: { todos: @todos }, tag: 'span'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
This custom renderer behaves the same as a normal view renderer and accepts the usual arguments - `content_type`, `layout`, `location` and `status`.
|
221
|
+
By default, your current layout will be used and the component, rather than a view, will be rendered in place of `yield`.
|
222
|
+
|
202
223
|
### Component generator
|
203
224
|
|
204
225
|
`react-rails` ships with a Rails generator to help you get started with a simple component scaffold.
|
@@ -230,7 +251,7 @@ var Post = React.createClass({
|
|
230
251
|
<div>Title: {this.props.title}</div>
|
231
252
|
<div>Body: {this.props.body}</div>
|
232
253
|
<div>Published: {this.props.published}</div>
|
233
|
-
<div>Published By: {this.props.
|
254
|
+
<div>Published By: {this.props.publishedBy}</div>
|
234
255
|
</div>
|
235
256
|
);
|
236
257
|
}
|
@@ -301,3 +322,42 @@ Component = React.createClass
|
|
301
322
|
render: ->
|
302
323
|
`<ExampleComponent videos={this.props.videos} />`
|
303
324
|
```
|
325
|
+
|
326
|
+
## Extending `react-rails`
|
327
|
+
|
328
|
+
You can extend some of the core functionality of `react-rails` by injecting new implementations during configuration.
|
329
|
+
|
330
|
+
### Custom Server Renderer
|
331
|
+
|
332
|
+
`react-rails` depends on a renderer class for rendering components on the server. You can provide a custom renderer class to `config.react.server_renderer`. The class must implement:
|
333
|
+
|
334
|
+
- `#initialize(options={})`, which accepts the hash from `config.react.server_renderer_options`
|
335
|
+
- `#render(component_name, props, prerender_options)` to return a string of HTML
|
336
|
+
|
337
|
+
`react-rails` provides two renderer classes: `React::ServerRendering::ExecJSRenderer` and `React::ServerRendering::SprocketsRenderer`.
|
338
|
+
|
339
|
+
`ExecJSRenderer` offers two other points for extension:
|
340
|
+
|
341
|
+
- `#before_render(component_name, props, prerender_options)` to return a string of JavaScript to execute _before_ calling `React.render`
|
342
|
+
- `#after_render(component_name, props, prerender_options)` to return a string of JavaScript to execute _after_ calling `React.render`
|
343
|
+
|
344
|
+
Any subclass of `ExecJSRenderer` may use those hooks (for example, `SprocketsRenderer` uses them to handle `console.*` on the server).
|
345
|
+
|
346
|
+
### Custom View Helper
|
347
|
+
|
348
|
+
`react-rails` uses a "helper implementation" class to generate the output of the `react_component` helper. The helper is initialized once per request and used for each `react_component` call during that request. You can provide a custom helper class to `config.react.view_helper_implementation`. The class must implement:
|
349
|
+
|
350
|
+
- `#react_component(name, props = {}, options = {}, &block)` to return a string to inject into the Rails view
|
351
|
+
- `#setup(rack_env)`, called when the helper is initialized at the start of the request
|
352
|
+
- `#teardown(rack_env)`, called at the end of the request
|
353
|
+
|
354
|
+
`react-rails` provides one implementation, `React::Rails::ComponentMount`.
|
355
|
+
|
356
|
+
### Custom JSX Transformer
|
357
|
+
|
358
|
+
`react-rails` uses a transformer class to transform JSX for the browser. The transformer is initialized once, at boot. You can provide a custom transformer to `config.react.jsx_transformer_class`. The transformer must implement:
|
359
|
+
|
360
|
+
- `#initialize(options)`, where options is the value passed to `config.react.jsx_transform_options`
|
361
|
+
- `#transform(code_string)` to return a string of transformed code
|
362
|
+
|
363
|
+
`react-rails` provides two transformers, `React::JSX::JSXTransformer` and `React::JSX::BabelTransformer`.
|
data/lib/react/jsx.rb
CHANGED
@@ -9,7 +9,7 @@ module React
|
|
9
9
|
DEFAULT_TRANSFORMER = BabelTransformer
|
10
10
|
mattr_accessor :transform_options, :transformer_class, :transformer
|
11
11
|
|
12
|
-
# You can assign `
|
12
|
+
# You can assign `config.react.jsx_transformer_class = `
|
13
13
|
# to provide your own transformer. It must implement:
|
14
14
|
# - #initialize(options)
|
15
15
|
# - #transform(code) => new code
|
data/lib/react/rails.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'react/rails/asset_variant'
|
2
2
|
require 'react/rails/engine'
|
3
3
|
require 'react/rails/railtie'
|
4
|
+
require 'react/rails/render_middleware'
|
4
5
|
require 'react/rails/version'
|
6
|
+
require 'react/rails/component_mount'
|
5
7
|
require 'react/rails/view_helper'
|
8
|
+
require 'react/rails/controller_renderer'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module React
|
2
|
+
module Rails
|
3
|
+
# This is the default view helper implementation.
|
4
|
+
# It just inserts HTML into the DOM (see {#react_component}).
|
5
|
+
#
|
6
|
+
# You can extend this class or provide your own implementation
|
7
|
+
# by assigning it to `config.react.view_helper_implementation`.
|
8
|
+
class ComponentMount
|
9
|
+
include ActionView::Helpers::TagHelper
|
10
|
+
include ActionView::Helpers::TextHelper
|
11
|
+
attr_accessor :output_buffer
|
12
|
+
|
13
|
+
# RenderMiddleware calls these hooks
|
14
|
+
# You can use them in custom helper implementations
|
15
|
+
def setup(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown(env)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Render a UJS-type HTML tag annotated with data attributes, which
|
22
|
+
# are used by react_ujs to actually instantiate the React component
|
23
|
+
# on the client.
|
24
|
+
def react_component(name, props = {}, options = {}, &block)
|
25
|
+
options = {:tag => options} if options.is_a?(Symbol)
|
26
|
+
|
27
|
+
prerender_options = options[:prerender]
|
28
|
+
if prerender_options
|
29
|
+
block = Proc.new{ concat React::ServerRendering.render(name, props, prerender_options) }
|
30
|
+
end
|
31
|
+
|
32
|
+
html_options = options.reverse_merge(:data => {})
|
33
|
+
html_options[:data].tap do |data|
|
34
|
+
data[:react_class] = name
|
35
|
+
data[:react_props] = (props.is_a?(String) ? props : props.to_json)
|
36
|
+
end
|
37
|
+
html_tag = html_options[:tag] || :div
|
38
|
+
|
39
|
+
# remove internally used properties so they aren't rendered to DOM
|
40
|
+
html_options.except!(:tag, :prerender)
|
41
|
+
|
42
|
+
content_tag(html_tag, '', html_options, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class React::Rails::ControllerRenderer
|
2
|
+
include React::Rails::ViewHelper
|
3
|
+
include ActionView::Helpers::TagHelper
|
4
|
+
include ActionView::Helpers::TextHelper
|
5
|
+
|
6
|
+
attr_accessor :output_buffer
|
7
|
+
|
8
|
+
attr_reader :request
|
9
|
+
def initialize(options={})
|
10
|
+
@request = options[:request]
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(name, options, &block)
|
14
|
+
props = options.fetch(:props, {})
|
15
|
+
options = options.slice(:data, :tag).merge(prerender: true)
|
16
|
+
react_component(name, props, options, &block)
|
17
|
+
end
|
18
|
+
end
|
data/lib/react/rails/railtie.rb
CHANGED
@@ -4,7 +4,6 @@ module React
|
|
4
4
|
module Rails
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
6
|
config.react = ActiveSupport::OrderedOptions.new
|
7
|
-
|
8
7
|
# Sensible defaults. Can be overridden in application.rb
|
9
8
|
config.react.variant = (::Rails.env.production? ? :production : :development)
|
10
9
|
config.react.addons = false
|
@@ -15,6 +14,8 @@ module React
|
|
15
14
|
config.react.server_renderer_timeout = 20 # seconds
|
16
15
|
config.react.server_renderer = nil # defaults to SprocketsRenderer
|
17
16
|
config.react.server_renderer_options = {} # SprocketsRenderer provides defaults
|
17
|
+
# View helper implementation:
|
18
|
+
config.react.view_helper_implementation = nil # Defaults to ComponentMount
|
18
19
|
|
19
20
|
# Watch .jsx files for changes in dev, so we can reload the JS VMs with the new JS code.
|
20
21
|
initializer "react_rails.add_watchable_files", group: :all do |app|
|
@@ -23,15 +24,27 @@ module React
|
|
23
24
|
|
24
25
|
# Include the react-rails view helper lazily
|
25
26
|
initializer "react_rails.setup_view_helpers", group: :all do |app|
|
27
|
+
app.config.middleware.use(::React::Rails::RenderMiddleware)
|
26
28
|
app.config.react.jsx_transformer_class ||= React::JSX::DEFAULT_TRANSFORMER
|
27
29
|
React::JSX.transformer_class = app.config.react.jsx_transformer_class
|
28
30
|
React::JSX.transform_options = app.config.react.jsx_transform_options
|
29
31
|
|
32
|
+
app.config.react.view_helper_implementation ||= React::Rails::ComponentMount
|
33
|
+
React::Rails::ViewHelper.helper_implementation_class = app.config.react.view_helper_implementation
|
30
34
|
ActiveSupport.on_load(:action_view) do
|
31
35
|
include ::React::Rails::ViewHelper
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
39
|
+
initializer "react_rails.add_component_renderer", group: :all do |app|
|
40
|
+
ActionController::Renderers.add :component do |component_name, options|
|
41
|
+
renderer = ::React::Rails::ControllerRenderer.new(request: request)
|
42
|
+
html = renderer.call(component_name, options)
|
43
|
+
render_options = options.merge(inline: html)
|
44
|
+
render(render_options)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
35
48
|
initializer "react_rails.bust_cache", group: :all do |app|
|
36
49
|
asset_variant = React::Rails::AssetVariant.new({
|
37
50
|
variant: app.config.react.variant,
|
@@ -43,7 +56,7 @@ module React
|
|
43
56
|
|
44
57
|
end
|
45
58
|
|
46
|
-
|
59
|
+
initializer "react_rails.set_variant", after: :engines_blank_point, group: :all do |app|
|
47
60
|
asset_variant = React::Rails::AssetVariant.new({
|
48
61
|
variant: app.config.react.variant,
|
49
62
|
addons: app.config.react.addons,
|
@@ -0,0 +1,19 @@
|
|
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
|
+
new_helper.setup(env)
|
12
|
+
env[HELPER_IMPLEMENTATION_KEY] = new_helper
|
13
|
+
response = @app.call(env)
|
14
|
+
new_helper.teardown(env)
|
15
|
+
response
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/react/rails/version.rb
CHANGED
@@ -1,28 +1,18 @@
|
|
1
1
|
module React
|
2
2
|
module Rails
|
3
3
|
module ViewHelper
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
4
|
+
# This class will be used for inserting tags into HTML.
|
5
|
+
# It should implement:
|
6
|
+
# - #setup(env)
|
7
|
+
# - #teardown(env)
|
8
|
+
# - #react_component(name, props, options &block)
|
9
|
+
# The default is {React::Rails::ComponentMount}
|
10
|
+
mattr_accessor :helper_implementation_class
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
html_options = options.reverse_merge(:data => {})
|
16
|
-
html_options[:data].tap do |data|
|
17
|
-
data[:react_class] = name
|
18
|
-
data[:react_props] = (props.is_a?(String) ? props : props.to_json)
|
19
|
-
end
|
20
|
-
html_tag = html_options[:tag] || :div
|
21
|
-
|
22
|
-
# remove internally used properties so they aren't rendered to DOM
|
23
|
-
html_options.except!(:tag, :prerender)
|
24
|
-
|
25
|
-
content_tag(html_tag, '', html_options, &block)
|
12
|
+
def react_component(*args, &block)
|
13
|
+
impl_key = React::Rails::RenderMiddleware::HELPER_IMPLEMENTATION_KEY
|
14
|
+
helper_obj = request.env[impl_key]
|
15
|
+
helper_obj.react_component(*args, &block)
|
26
16
|
end
|
27
17
|
end
|
28
18
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: react-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul O’Shannessy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -270,8 +270,11 @@ files:
|
|
270
270
|
- lib/react/jsx/template.rb
|
271
271
|
- lib/react/jsx.rb
|
272
272
|
- lib/react/rails/asset_variant.rb
|
273
|
+
- lib/react/rails/component_mount.rb
|
274
|
+
- lib/react/rails/controller_renderer.rb
|
273
275
|
- lib/react/rails/engine.rb
|
274
276
|
- lib/react/rails/railtie.rb
|
277
|
+
- lib/react/rails/render_middleware.rb
|
275
278
|
- lib/react/rails/version.rb
|
276
279
|
- lib/react/rails/view_helper.rb
|
277
280
|
- lib/react/rails.rb
|