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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15df12f33d7eebb048c97c8cd0bb64e95ccce6aa
4
- data.tar.gz: ed212e1fdfa9fd6aa5f401cf931e9d0d72a22d24
3
+ metadata.gz: fcffb8326ddf9468f84991dc075b824339192aa6
4
+ data.tar.gz: 732958fbaa2b917816cc4febcd340e4d439ac397
5
5
  SHA512:
6
- metadata.gz: 426958555a561b2b3bd2ea3954919123b5f7cbc764892c426b3d461b43650384fc5f1d570a65eb8eec156aac9108f1917b98987cbeff71ce50ecce270220d10b
7
- data.tar.gz: c2c7cd00745aa11c70c04295d6aeb8461777a1279dacafcc48df1ea2b4bffba025de5130953ba1c829f7c3e8350b26c79297f042d3cab42cf330b51eb3b01706
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
- To use old JSXTransformer you can use `React::JSX.transformer_class = React::JSX::JSXTransformer`
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.published_by}</div>
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`.
@@ -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 `React::JSX.transformer_class = `
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
@@ -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
@@ -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
- config.before_initialize do |app|
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
@@ -1,6 +1,6 @@
1
1
  module React
2
2
  module Rails
3
3
  # If you change this, make sure to update VERSIONS.md
4
- VERSION = '1.2.0'
4
+ VERSION = '1.3.0'
5
5
  end
6
6
  end
@@ -1,28 +1,18 @@
1
1
  module React
2
2
  module Rails
3
3
  module ViewHelper
4
- # Render a UJS-type HTML tag annotated with data attributes, which
5
- # are used by react_ujs to actually instantiate the React component
6
- # on the client.
7
- def react_component(name, props = {}, options = {}, &block)
8
- options = {:tag => options} if options.is_a?(Symbol)
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
- prerender_options = options[:prerender]
11
- if prerender_options
12
- block = Proc.new{ concat React::ServerRendering.render(name, props, prerender_options) }
13
- end
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.2.0
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-08-19 00:00:00.000000000 Z
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