react-rails 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|