react_on_rails 3.0.6 → 4.0.0.beta.1

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: 5957258eac9feb1ceb153281ac4c4675f51cdf33
4
- data.tar.gz: 403c21f1a5e6c898130fcebc552b03a98fe52422
3
+ metadata.gz: fbaf8ec483e9950e41d61c2e22b62b325113b00a
4
+ data.tar.gz: 6e2da43df3e19adaffa7ff8a386fd39faa55c4b9
5
5
  SHA512:
6
- metadata.gz: 814f7d546c1b4f9d76b84f0f5c385599e431724c6b9b1e191e51afb0cbcc0063186559b6f565e282b6f15153a08899744b13c5be42245e593a92e6e00a251efc
7
- data.tar.gz: bb9c0eb29e8213664365558ad5a8cf2c006e7dad86e2660174cf53e13666747007d95596b16699fff39a532a8c66c64827e6729e7ec44bcc67eb7c835073310f
6
+ metadata.gz: 9f716fc038e89ab1f26049d01bc9cfce53717cd40f0705c94a92906aee8f1f340b1b9e1eeb6adddfcf9bb4cc889de3b2638645b7fb78990b543fda4933c80b3c
7
+ data.tar.gz: 6befd861e58a261de37c42eb332156bd67b125dbbe0823e6d2a42a59b02c0cd8fe4ed5ea49ded2e97d438829d48a206ffe73bd4d03048d6fc595d19fd2d5649d
@@ -12,7 +12,7 @@ gemfile:
12
12
  - spec/dummy/Gemfile
13
13
 
14
14
  env:
15
- - export RAILS_ENV=test DRIVER=selenium_chrome
15
+ - export RAILS_ENV=test DRIVER=selenium
16
16
 
17
17
  before_install:
18
18
  - sudo apt-get update
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. Items under
4
4
  Contributors: please follow the recommendations outlined at [keepachangelog.com](http://keepachangelog.com/). Please use the existing headings and styling as a guide, and add a link for the version diff at the bottom of the file. Also, please update the `Unreleased` link to compare to the latest release version.
5
5
  ## [Unreleased]
6
6
 
7
+ ## [4.0.0.rc.1] - 2016-03-06
8
+ ##### Added
9
+ - Added controller `module ReactOnRails::Controller`. Adds method `redux_store` to setup redux stores in the view.
10
+ - Added view helper `redux_store_hydration_data` to render the props on the application's layout, near the bottom. This allows for the client hydration data to be parsed after the server rendering, which may result in a faster load time.
11
+ - Added helpers `env_stylesheet_link_tag` and `env_javascript_include_tag` to support hot reloading Rails. See the [README.md](./README.md) for more details and see the example application in `spec/dummy`.
12
+ - The checker for outdated bundles before running tests will default to including the directory with `server_bundle_js_file`.
13
+
14
+ ##### Fixed
15
+ - The test runner assets up to date checker might see only the server rendering file, and assume that all assets are up to date.
16
+ - Lots of doc updates!
17
+ - Improved the **spec/dummy** sample app so that it supports CSS modules, hot reloading, etc, and it can server as a template for a new ReactOnRails installation.
18
+
19
+ ##### Breaking Changes
20
+ - Deprecated `redux_store` called from views. Call this method from your controller actions and place `redux_store_hydration_data` on your layout, near the bottom.
21
+ - Removed the config default of the `config.server_bundle_js_file`. The default is blank, meaning no server rendering.
22
+
23
+
7
24
  ## [3.0.6] - 2016-03-01
8
25
  ##### Fixed
9
26
  - Improved errors when registered store is not found. See [#301](https://github.com/shakacode/react_on_rails/pull/301) by [justin808](https://github.com/justin808).
@@ -192,7 +209,8 @@ Best done with Object destructing:
192
209
 
193
210
  ##### Fixed
194
211
  - Fix several generator related issues.
195
- [Unreleased]: https://github.com/shakacode/react_on_rails/compare/3.0.5...master
212
+ [Unreleased]: https://github.com/shakacode/react_on_rails/compare/3.0.6...master
213
+ [3.0.6]: https://github.com/shakacode/react_on_rails/compare/3.0.5...3.0.6
196
214
  [3.0.5]: https://github.com/shakacode/react_on_rails/compare/3.0.4...3.0.5
197
215
  [3.0.4]: https://github.com/shakacode/react_on_rails/compare/3.0.3...3.0.4
198
216
  [3.0.3]: https://github.com/shakacode/react_on_rails/compare/3.0.2...3.0.3
data/Gemfile CHANGED
@@ -8,8 +8,6 @@ gemspec
8
8
  # bundle install from a single Gemfile. Therefore, all gems that we will need for any dummy/example
9
9
  # app have to be manually added to this file.
10
10
  gem "bootstrap-sass"
11
- gem "capybara"
12
- gem "capybara-screenshot"
13
11
  gem "chromedriver-helper"
14
12
  gem "coffee-rails", "~> 4.1.0"
15
13
  gem "jbuilder", "~> 2.0"
@@ -19,13 +17,11 @@ gem "poltergeist"
19
17
  gem "puma"
20
18
  gem "rails", "4.2.5"
21
19
  gem "rails_12factor"
22
- gem "rspec-rails"
23
20
  gem "rubocop", require: false
24
21
  gem "ruby-lint", require: false
25
22
  gem "sass-rails", "~> 5.0"
26
23
  gem "scss_lint", require: false
27
24
  gem "sdoc", "~> 0.4.0", group: :doc
28
- gem "selenium-webdriver"
29
25
  gem "spring"
30
26
  gem "sqlite3"
31
27
  gem "therubyracer"
@@ -36,3 +32,15 @@ else
36
32
  end
37
33
  gem "uglifier", ">= 2.7.2"
38
34
  gem "web-console", "~> 2.0", group: :development
35
+
36
+ # below are copied from spec/dummy/Gemfile
37
+ gem "rspec-rails"
38
+ gem "coveralls", require: false
39
+ gem "capybara"
40
+ gem "capybara-screenshot"
41
+ gem "capybara-webkit"
42
+ gem "chromedriver-helper"
43
+ gem "generator_spec"
44
+ gem "launchy"
45
+ gem "poltergeist"
46
+ gem "selenium-webdriver"
@@ -7,6 +7,7 @@
7
7
  * **[GuavaPass](https://guavapass.com/)**: Coaching client of [ShakaCode](http://www.shakacode.com) and React on Rails fan!
8
8
  * **Friends and Guests**, the signature product of [ShakaCode](http://www.shakacode.com), which is a "Social Network Connecting Hosts and Guests". *Coming soon!*
9
9
  * **[Madrone Analytics](http://madroneco.com/)**: The original client of [ShakaCode](http://www.shakacode.com) that led to the development of React on Rails, as described in [Fast Rich Client Rails Development With Webpack and the ES6 Transpiler](http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/).
10
+ * **[Pivotal Tracker](http://www.pivotaltracker.com/)**: The first (and most-loved) agile project management tool built on Rails. React on Rails has greatly simplified integration and workflow for our React components in Rails!
10
11
 
11
12
  --------
12
13
 
data/README.md CHANGED
@@ -75,7 +75,8 @@ Please see [Getting Started](#getting-started) for how to set up your Rails proj
75
75
  - [Client-Side Rendering vs. Server-Side Rendering](#client-side-rendering-vs-server-side-rendering)
76
76
  - [Building the Bundles](#building-the-bundles)
77
77
  - [Globally Exposing Your React Components](#globally-exposing-your-react-components)
78
- - [Rails View Helpers In-Depth](#rails-view-helpers-in-depth)
78
+ - [ReactOnRails View Helpers API](#reactonrails-view-helpers-api)
79
+ - [ReactOnRails JavaScript API](#reactonrails-javascript-api)
79
80
  - [Redux](#redux)
80
81
  - [React-Router](#react-router)
81
82
  + [Generator](#generator)
@@ -220,12 +221,12 @@ Place your JavaScript code inside of the provided `client/app` folder. Use modul
220
221
 
221
222
  In general, you may want different initialization for your server rendered components.
222
223
 
223
- ### Rails View Helpers In-Depth
224
+ ## ReactOnRails View Helpers API
224
225
  Once the bundled files have been generated in your `app/assets/javascripts/generated` folder and you have exposed your components globally, you will want to run your code in your Rails views using the included helper method.
225
226
 
226
227
  This is how you actually render the React components you exposed to `window` inside of `clientRegistration` (and `global` inside of `serverRegistration` if you are server rendering).
227
228
 
228
- #### react_component
229
+ ### react_component
229
230
  `react_component(component_name, options = {})`
230
231
 
231
232
  + **component_name:** Can be a React component, created using a ES6 class, or `React.createClass`, or a generator function that returns a React component.
@@ -238,7 +239,10 @@ This is how you actually render the React components you exposed to `window` ins
238
239
  + **raise_on_prerender_error:** Default is false. True will throw an error on the server side rendering. Your controller will have to handle the error.
239
240
  + Any other options are passed to the content tag, including the id
240
241
 
241
- #### redux_store
242
+ ### redux_store
243
+ #### Controller Extension
244
+ Include the module ReactOnRails::Controller in your controller, probably in ApplicationController. This will provide the following controller method, which you can call in your controller actions:
245
+
242
246
  `redux_store(store_name, props = {})`
243
247
 
244
248
  + **store_name:** A name for the store. You'll refer to this name in 2 places in your JavaScript:
@@ -246,10 +250,23 @@ This is how you actually render the React components you exposed to `window` ins
246
250
  2. In your component definition, you'll call `ReactOnRails.getStore('storeName')` to get the hydrated Redux store to attach to your components.
247
251
  + **props:** ReactOnRails takes care of setting up the hydration of your store with props from the view.
248
252
 
249
- #### Generator Functions
253
+ For an example, see [spec/dummy/app/controllers/pages_controller.rb](spec/dummy/app/controllers/pages_controller.rb).
254
+
255
+ #### View Helper
256
+ `redux_store_hydration_data`
257
+
258
+ Place this view helper (no parameters) at the end of your shared layout. This tell ReactOnRails where to client render the redux store hydration data. Since we're going to be setting up the stores in the controllers, we need to know where on the view to put the client side rendering of this hydration data, which is a hidden div with a matching class that contains a data props. For an example, see [spec/dummy/app/views/layouts/application.html.erb](spec/dummy/app/views/layouts/application.html.erb).
259
+
260
+ #### Redux Store Notes
261
+ Note, you don't need to separately initialize your redux store. However, it's recommended for the two following use cases:
262
+
263
+ 1. You want to have multiple components that access the same store.
264
+ 2. You want to place the props to hydrate the client side stores at the very end of your HTML, so the browser can render all earlier HTML first. This is particularly useful if your props will be large.
265
+
266
+ ### Generator Functions
250
267
  Why would you create a function that returns a React compnent? For example, you may want the ability to use the passed-in props to initialize a redux store or setup react-router. Or you may want to return different components depending on what's in the props. ReactOnRails will automatically detect a registered generator function.
251
268
 
252
- #### server_render_js
269
+ ### server_render_js
253
270
  `server_render_js(js_expression, options = {})`
254
271
 
255
272
  + js_expression, like 2 + 3, and not a block of js code. If you have more than one line that needs to be executed, wrap it in an [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression). JS exceptions will be caught and console messages handled properly
@@ -257,8 +274,93 @@ Why would you create a function that returns a React compnent? For example, you
257
274
 
258
275
  This is a helper method that takes any JavaScript expression and returns the output from evaluating it. If you have more than one line that needs to be executed, wrap it in an IIFE. JS exceptions will be caught and console messages handled properly.
259
276
 
277
+ ## ReactOnRails JavaScript API
278
+ The best source of docs is the main [ReactOnRails.js](node_package/src/ReactOnRails.js) file. Here's a quick summary. No guarantees that this won't be outdated!
279
+
280
+ ```js
281
+ /**
282
+ * Main entry point to using the react-on-rails npm package. This is how Rails will be able to
283
+ * find you components for rendering.
284
+ * @param components (key is component name, value is component)
285
+ */
286
+ register(components)
287
+
288
+ /**
289
+ * Allows registration of store generators to be used by multiple react components on one Rails
290
+ * view. store generators are functions that take one arg, props, and return a store. Note that
291
+ * the setStore API is different in tha it's the actual store hydrated with props.
292
+ * @param stores (key is store name, value is the store generator)
293
+ */
294
+ registerStore(stores)
295
+
296
+ /**
297
+ * Allows retrieval of the store by name. This store will be hydrated by any Rails form props.
298
+ * Pass optional param throwIfMissing = false if you want to use this call to get back null if the
299
+ * store with name is not registered.
300
+ * @param name
301
+ * @param throwIfMissing Defaults to true. Set to false to have this call return undefined if
302
+ * there is no store with the given name.
303
+ * @returns Redux Store, possibly hydrated
304
+ */
305
+ getStore(name, throwIfMissing = true )
306
+
307
+ /**
308
+ * Set options for ReactOnRails, typically before you call ReactOnRails.register
309
+ * Available Options:
310
+ * `traceTurbolinks: true|false Gives you debugging messages on Turbolinks events
311
+ */
312
+ setOptions(options)
313
+ ```
314
+
315
+ ## Hot Reloading View Helpers
316
+ The `env_javascript_include_tag` and `env_stylesheet_link_tag` support the usage of a webpack dev server for providing the JS and CSS assets during development mode. See the [shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/) for a working example.
317
+
318
+ The key options are `static` and `hot` which specify what you want for static vs. hot. Both of these params are optional, and support either a single value, or an array.
319
+
320
+ static vs. hot is picked based on whether ENV["REACT_ON_RAILS_ENV"] == "HOT"
321
+
322
+ ```erb
323
+ <%= env_stylesheet_link_tag(static: 'application_static',
324
+ hot: 'application_non_webpack',
325
+ media: 'all',
326
+ 'data-turbolinks-track' => true) %>
327
+
328
+ <!-- These do not use turbolinks, so no data-turbolinks-track -->
329
+ <!-- This is to load the hot assets. -->
330
+ <%= env_javascript_include_tag(hot: ['http://localhost:3500/vendor-bundle.js',
331
+ 'http://localhost:3500/app-bundle.js']) %>
332
+
333
+ <!-- These do use turbolinks -->
334
+ <%= env_javascript_include_tag(static: 'application_static',
335
+ hot: 'application_non_webpack',
336
+ 'data-turbolinks-track' => true) %>
337
+ ```
338
+
339
+ See application.html.erb for usage example and [application.html.erb](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/app%2Fviews%2Flayouts%2Fapplication.html.erb)
340
+
341
+ **env_javascript_include_tag(args = {})**
342
+
343
+ Helper to set CSS assets depending on if we want static or "hot", which means from the Webpack dev server.
344
+
345
+ In this example, application_non_webpack is simply a CSS asset pipeline file which includes styles not placed in the webpack build.
346
+
347
+ We don't need styles from the webpack build, as those will come via the JavaScript include tags.
348
+
349
+ The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
350
+ these params are optional, and support either a single value, or an array.
351
+
352
+ ```erb
353
+ <%= env_stylesheet_link_tag(static: 'application_static',
354
+ hot: 'application_non_webpack',
355
+ media: 'all',
356
+ 'data-turbolinks-track' => true) %>
357
+ ```
358
+
359
+ **env_stylesheet_link_tag(args = {})**
360
+
361
+
260
362
  ## Generator
261
- The `react_on_rails:install` generator combined with the example pull requests of generator runs will get you up and running efficiently. There's a fair bit of setup with integrating Webpack with Rails. Defaults for options are such that the default is for the flag to be off. For example, the default for `-R` is that `redux` is off, and the default of `-b` means that `skip-bootstrap` is off.
363
+ The `react_on_rails:install` generator combined with the example pull requests of generator runs will get you up and running efficiently. There's a fair bit of setup with integrating Webpack with Rails. Defaults for options are such that the default is for the flag to be off. For example, the default for `-R` is that `redux` is off, and the default of `-b` is that `skip-bootstrap` is off.
262
364
 
263
365
  Run `rails generate react_on_rails:install --help` for descriptions of all available options:
264
366
 
@@ -380,7 +482,7 @@ Bootstrap integration is enabled by default, but can be disabled by passing the
380
482
  The React on Rails generator can add linters and their recommended accompanying configurations to your project. There are two classes of linters: ruby linters and JavaScript linters.
381
483
 
382
484
  ##### JavaScript Linters
383
- JavaScript linters are **enabled by default**, but can be disabled by passing the `--skip-js-linters` flag (alias `j`) , and those that run in Node have been add to `client/package.json` under `devDependencies`.
485
+ JavaScript linters are **enabled by default**, but can be disabled by passing the `--skip-js-linters` flag (alias `j`) , and those that run in Node have been added to `client/package.json` under `devDependencies`.
384
486
 
385
487
  ##### Ruby Linters
386
488
  Ruby linters are **disabled by default**, but can be enabled by passing the `--ruby-linters` flag when generating. These linters have been added to your Gemfile in addition to the appropriate Rake tasks.
@@ -1,3 +1,4 @@
1
+ # rubocop:disable Metrics/ModuleLength
1
2
  # NOTE:
2
3
  # For any heredoc JS:
3
4
  # 1. The white spacing in this file matters!
@@ -5,6 +6,57 @@
5
6
  require "react_on_rails/prerender_error"
6
7
 
7
8
  module ReactOnRailsHelper
9
+ # The env_javascript_include_tag and env_stylesheet_link_tag support the usage of a webpack
10
+ # dev server for providing the JS and CSS assets during development mode. See
11
+ # https://github.com/shakacode/react-webpack-rails-tutorial/ for a working example.
12
+ #
13
+ # The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
14
+ # these params are optional, and support either a single value, or an array.
15
+ #
16
+ # static vs. hot is picked based on whether
17
+ # ENV["REACT_ON_RAILS_ENV"] == "HOT"
18
+ #
19
+ # <%= env_stylesheet_link_tag(static: 'application_static',
20
+ # hot: 'application_non_webpack',
21
+ # media: 'all',
22
+ # 'data-turbolinks-track' => true) %>
23
+ #
24
+ # <!-- These do not use turbolinks, so no data-turbolinks-track -->
25
+ # <!-- This is to load the hot assets. -->
26
+ # <%= env_javascript_include_tag(hot: ['http://localhost:3500/vendor-bundle.js',
27
+ # 'http://localhost:3500/app-bundle.js']) %>
28
+ #
29
+ # <!-- These do use turbolinks -->
30
+ # <%= env_javascript_include_tag(static: 'application_static',
31
+ # hot: 'application_non_webpack',
32
+ # 'data-turbolinks-track' => true) %>
33
+ # See application.html.erb for usage example
34
+ # https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/app%2Fviews%2Flayouts%2Fapplication.html.erb
35
+ def env_javascript_include_tag(args = {})
36
+ send_tag_method(:javascript_include_tag, args)
37
+ end
38
+
39
+ # Helper to set CSS assets depending on if we want static or "hot", which means from the
40
+ # Webpack dev server.
41
+ #
42
+ # In this example, application_non_webpack is simply a CSS asset pipeline file which includes
43
+ # styles not placed in the webpack build.
44
+ #
45
+ # We don't need styles from the webpack build, as those will come via the JavaScript include
46
+ # tags.
47
+ #
48
+ # The key options are `static` and `hot` which specify what you want for static vs. hot. Both of
49
+ # these params are optional, and support either a single value, or an array.
50
+ #
51
+ # <%= env_stylesheet_link_tag(static: 'application_static',
52
+ # hot: 'application_non_webpack',
53
+ # media: 'all',
54
+ # 'data-turbolinks-track' => true) %>
55
+ #
56
+ def env_stylesheet_link_tag(args = {})
57
+ send_tag_method(:stylesheet_link_tag, args)
58
+ end
59
+
8
60
  # react_component_name: can be a React component, created using a ES6 class, or
9
61
  # React.createClass, or a
10
62
  # `generator function` that returns a React component
@@ -89,28 +141,41 @@ module ReactOnRailsHelper
89
141
  # IMPORTANT: Ensure that we mark string as html_safe to avoid escaping.
90
142
  <<-HTML.html_safe
91
143
  #{component_specification_tag}
92
- #{rendered_output}
93
- #{replay_console(options) ? console_script : ''}
144
+ #{rendered_output}
145
+ #{replay_console(options) ? console_script : ''}
94
146
  HTML
95
147
  end
96
148
 
149
+ # Deprecated: Use `redux_store` via including ReactOnRails::Controller in your controller and calling
150
+ # redux_store.
151
+ #
97
152
  # Separate initialization of store from react_component allows multiple react_component calls to
98
153
  # use the same Redux store.
99
154
  #
100
155
  # store_name: name of the store, corresponding to your call to ReactOnRails.registerStores in your
101
156
  # JavaScript code.
102
- # props: Ruby Hash or JSON string which contains the properties to pass to the redux storea.
157
+ # props: Ruby Hash or JSON string which contains the properties to pass to the redux store.
103
158
  def redux_store(store_name, props = {})
159
+ warn "[DEPRECATION] `redux_store` within a view is deprecated. Please move to call "\
160
+ "to redux store to your controller action."
104
161
  redux_store_data = { store_name: store_name,
105
162
  props: props }
106
163
  @registered_stores ||= []
107
164
  @registered_stores << redux_store_data
108
165
 
109
- content_tag(:div,
110
- "",
111
- class: "js-react-on-rails-store",
112
- style: ReactOnRails.configuration.skip_display_none ? nil : "display:none",
113
- data: redux_store_data)
166
+ render_redux_store_data(redux_store_data)
167
+ end
168
+
169
+ # Place this view helper (no parameters) at the end of your shared layout. This tell
170
+ # ReactOnRails where to client render the redux store hydration data. Since we're going
171
+ # to be setting up the stores in the controllers, we need to know where on the view to put the
172
+ # client side rendering of this hydration data, which is a hidden div with a matching class
173
+ # that contains a data props.
174
+ def redux_store_hydration_data
175
+ return if @registered_stores_via_controller.blank?
176
+ @registered_stores_via_controller.reduce("") do |accum, redux_store_data|
177
+ accum << render_redux_store_data(redux_store_data)
178
+ end.html_safe
114
179
  end
115
180
 
116
181
  def sanitized_props_string(props)
@@ -165,6 +230,14 @@ module ReactOnRailsHelper
165
230
 
166
231
  private
167
232
 
233
+ def render_redux_store_data(redux_store_data)
234
+ content_tag(:div,
235
+ "",
236
+ class: "js-react-on-rails-store",
237
+ style: ReactOnRails.configuration.skip_display_none ? nil : "display:none",
238
+ data: redux_store_data)
239
+ end
240
+
168
241
  def next_react_component_index
169
242
  @react_component_index ||= -1
170
243
  @react_component_index += 1
@@ -206,12 +279,12 @@ module ReactOnRailsHelper
206
279
  if result["hasErrors"] && raise_on_prerender_error(options)
207
280
  # We caught this exception on our backtrace handler
208
281
  # rubocop:disable Style/RaiseArgs
209
- fail ReactOnRails::PrerenderError.new(component_name: react_component_name,
210
- # Sanitize as this might be browser logged
211
- props: sanitized_props_string(props),
212
- err: nil,
213
- js_code: wrapper_js,
214
- console_messages: result["consoleReplayScript"])
282
+ raise ReactOnRails::PrerenderError.new(component_name: react_component_name,
283
+ # Sanitize as this might be browser logged
284
+ props: sanitized_props_string(props),
285
+ err: nil,
286
+ js_code: wrapper_js,
287
+ console_messages: result["consoleReplayScript"])
215
288
  # rubocop:enable Style/RaiseArgs
216
289
  end
217
290
  result
@@ -227,9 +300,12 @@ module ReactOnRailsHelper
227
300
  end
228
301
 
229
302
  def initialize_redux_stores
230
- return "" unless @registered_stores.present?
303
+ return "" unless @registered_stores.present? || @registered_stores_via_controller.present?
231
304
  declarations = "var reduxProps, store, storeGenerator;\n"
232
- result = @registered_stores.each_with_object(declarations) do |redux_store_data, memo|
305
+
306
+ all_stores = (@registered_stores || []) + (@registered_stores_via_controller || [])
307
+
308
+ result = all_stores.each_with_object(declarations) do |redux_store_data, memo|
233
309
  store_name = redux_store_data[:store_name]
234
310
  props = props_string(redux_store_data[:props])
235
311
  memo << <<-JS
@@ -290,4 +366,15 @@ ReactOnRails.setStore('#{store_name}', store);
290
366
  end
291
367
  [final_options, props]
292
368
  end
369
+
370
+ def use_hot_reloading?
371
+ ENV["REACT_ON_RAILS_ENV"] == "HOT"
372
+ end
373
+
374
+ def send_tag_method(tag_method_name, args)
375
+ asset_type = use_hot_reloading? ? :hot : :static
376
+ assets = Array(args[asset_type])
377
+ options = args.delete_if { |key, _value| %i(hot static).include?(key) }
378
+ send(tag_method_name, *assets, options) unless assets.empty?
379
+ end
293
380
  end
@@ -18,9 +18,9 @@ Assuming you have downloaded and installed the Heroku command-line utility and h
18
18
  heroku buildpacks:set https://github.com/heroku/heroku-buildpack-multi
19
19
  ```
20
20
 
21
- Heroku will now be able to use the multiple buildpacks specified in `.buildpacks`.
21
+ Heroku will now be able to use the multiple buildpacks specified in `.buildpacks`.
22
22
 
23
- Note, an alternative approach is to use the [Heroku Toolbelt to set buildpacks](https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app).
23
+ For more information, see [Using Multiple Buildpacks for an App](https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app)
24
24
 
25
25
  ## Fresh Rails Install
26
26
 
@@ -0,0 +1,32 @@
1
+ # Hot Reloading of Assets For Rails Development
2
+
3
+ This document outlines the steps to setup your React On Rails Environment so that you can experience the pleasure of hot reloading of JavaScript and Sass during your Rails development work. There are 2 examples of this setup:
4
+ 1. [spec/dummy](../spec/dummy): Simpler setup used for integration testing this gem.
5
+ 1. [shakacode/react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/). Full featured setup using Twitter bootstrap.
6
+
7
+ ## High Level Strategy
8
+
9
+ We'll use a Webpack Dev server on port 3500 to provide the assets to Rails, rather than the asset pipeline, and only during development mode. This is configured via the `Procfile.hot`.
10
+
11
+ `Procfile.static` provides an alternative that uses "static" assets, similar to a production deployment.
12
+
13
+ The secret sauce is in the [app/views/layouts/application.html.erb](spec/dummy/app/views/layouts/application.html.erb) where it uses view helpes to configure the correct assets to load, being either the "hot" assets or the "static" assets.
14
+
15
+ ## Places to Configure (Files to Examine)
16
+
17
+ 1. See the Webpack config files. Note, these examples are now setup for using [CSS Modules](https://github.com/css-modules/css-modules).
18
+ 1. [client/webpack.client.base.config.js](spec/dummy/client/webpack.client.base.config.js): Common configuration for hot or static assets.
19
+ 1. [client/webpack.client.hot.config.js](spec/dummy/client/webpack.client.hot.config.js): Setup for hot loading, using react-transform-hmr.
20
+ 1. [client/webpack.client.static.config.js](spec/dummy/client/webpack.client.static.config.js): Setup for static loading, as is done in a production deployment.
21
+ 1. [app/views/layouts/application.html.erb](spec/dummy/app/views/layouts/application.html.erb): Uses the view helpers `env_stylesheet_link_tag` and `env_javascript_include_tag` which will either do the hot reloading or the static loading.
22
+ 1. See the Procfiles: [Procfile.hot](spec/dummy/Procfile.hot) and [Procfile.static](spec/dummy/Procfile.static). These:
23
+ 1. Start the webpack processes, depending on the mode or HOT or not.
24
+ 2. Start the rails server, setting an ENV value of REACT_ON_RAILS_ENV to HOT if we're hot loading or else setting this to blank.
25
+ 1. Configure the file Rails asset pipeline files:
26
+ 1. [app/assets/javascripts/application_static.js.erb](spec/dummy/app/assets/javascripts/application_static.js.erb): We have to only specify the `vendor-bundle` and `app-bundle` if we're not HOT loading, as Sprockets will throw an error if that is the case. Note the use of `require_asset`.
27
+ 1. [app/assets/stylesheets/application_static.js.erb](spec/dummy/app/assets/stylesheets/application_static.scss.erb): We have to only specify the `vendor-bundle` and `app-bundle` if we're not HOT loading, as Sprockets will throw an error if that is the case. Note the conditional around the @import.
28
+ 1. Be sure your [config/initializers/assets.rb](spec/dummy/config/initializers/assets.rb) is configured to include the webpack generated files.
29
+ 1. Copy the [client/server-rails-hot.js](spec/dummy/client/server-rails-hot.js) to the [client](client) directory.
30
+ 1. Copy the scripts in the top level and client level `package.json` files:
31
+ 1. Top Level: [package.json](spec/dummy/package.json)
32
+ 1. Client Level: [package.json](spec/dummy/client/package.json)
@@ -2,9 +2,9 @@ Description:
2
2
 
3
3
  The react_on_rails:install generator combined with the example pull requests of
4
4
  generator runs will get you up and running efficiently. There's a fair bit of
5
- setup involved when ~with~ integrating Webpack with Rails. Defaults for options
5
+ setup involved when integrating Webpack with Rails. Defaults for options
6
6
  are such that the default is for the flag to be off. For example, the default for
7
- `-R` is that redux is off, and the default of -b means that skip-bootstrap is off.
7
+ `-R` is that redux is off, and the default of -b is that skip-bootstrap is off.
8
8
 
9
9
  * Redux
10
10
 
@@ -83,7 +83,7 @@ are such that the default is for the flag to be off. For example, the default fo
83
83
  * JavaScript Linters
84
84
 
85
85
  JavaScript linters are enabled by default, but can be disabled by passing the
86
- --skip-js-linters flag (alias j), and those that run in Node have been add to
86
+ --skip-js-linters flag (alias j), and those that run in Node have been added to
87
87
  `client/package.json` under devDependencies.
88
88
 
89
89
  * Ruby Linters
@@ -1,5 +1,6 @@
1
1
  require "rails"
2
2
 
3
+ require "react_on_rails/controller"
3
4
  require "react_on_rails/version"
4
5
  require "react_on_rails/version_checker"
5
6
  require "react_on_rails/configuration"
@@ -4,14 +4,13 @@ module ReactOnRails
4
4
  end
5
5
 
6
6
  DEFAULT_GENERATED_ASSETS_DIRS = [
7
- %w(app assets javascripts generated),
8
- %w(app assets javascripts stylesheets generated)
7
+ %w(app assets webpack)
9
8
  ].map { |dirs| File.join(*dirs) }.freeze
10
9
 
11
10
  def self.configuration
12
11
  @configuration ||= Configuration.new(
13
12
  generated_assets_dirs: DEFAULT_GENERATED_ASSETS_DIRS,
14
- server_bundle_js_file: File.join(*%w(app assets javascripts generated server.js)),
13
+ server_bundle_js_file: "",
15
14
  prerender: false,
16
15
  replay_console: true,
17
16
  logging_on_server: true,
@@ -0,0 +1,19 @@
1
+ module ReactOnRails
2
+ module Controller
3
+ # Separate initialization of store from react_component allows multiple react_component calls to
4
+ # use the same Redux store.
5
+ #
6
+ # store_name: name of the store, corresponding to your call to ReactOnRails.registerStores in your
7
+ # JavaScript code.
8
+ # props: Ruby Hash or JSON string which contains the properties to pass to the redux store.
9
+ #
10
+ # Be sure to include view helper `redux_store_hydration_data` at the end of your layout or view
11
+ # or else there will be no client side hydration of your stores.
12
+ def redux_store(store_name, props)
13
+ redux_store_data = { store_name: store_name,
14
+ props: props }
15
+ @registered_stores_via_controller ||= []
16
+ @registered_stores_via_controller << redux_store_data
17
+ end
18
+ end
19
+ end
@@ -38,20 +38,39 @@ module ReactOnRails
38
38
  # defaults to ReactOnRails::TestHelper::WebpackProcessChecker
39
39
  # webpack_assets_compiler: provide one method: `def compile`
40
40
  # defaults to ReactOnRails::TestHelper::WebpackAssetsCompiler
41
+ # server_bundle_js_file: The server rendering file, defaulting to server_bundle_js_file in
42
+ # your config
41
43
  # client_dir and compiled_dirs are passed into the default webpack_assets_status_checker if you
42
44
  # don't provide one.
43
45
  def self.ensure_assets_compiled(webpack_assets_status_checker: nil,
44
- webpack_assets_compiler: nil,
45
- webpack_process_checker: nil,
46
- client_dir: nil,
47
- compiled_dirs: nil)
46
+ webpack_assets_compiler: nil,
47
+ webpack_process_checker: nil,
48
+ client_dir: nil,
49
+ compiled_dirs: nil,
50
+ server_bundle_js_file: nil)
48
51
 
49
52
  if webpack_assets_status_checker.nil?
50
53
  client_dir ||= Rails.root.join("client")
51
54
  compiled_dirs ||= ReactOnRails.configuration.generated_assets_dirs
55
+ server_bundle_js_file ||= ReactOnRails.configuration.server_bundle_js_file
56
+
57
+ if server_bundle_js_file.present?
58
+ dir = File.dirname(server_bundle_js_file)
59
+ compiled_dirs ||= []
60
+ compiled_dirs << dir unless compiled_dirs.include?(dir)
61
+ end
52
62
  webpack_assets_status_checker ||=
53
63
  WebpackAssetsStatusChecker.new(client_dir: client_dir,
54
- compiled_dirs: compiled_dirs)
64
+ compiled_dirs: compiled_dirs,
65
+ server_bundle_js_file: server_bundle_js_file)
66
+
67
+ unless @printed_once
68
+ puts
69
+ puts "====> React On Rails: Checking dirs for outdated/missing bundles: "\
70
+ "#{webpack_assets_status_checker.compiled_dirs}"
71
+ puts
72
+ @printed_once = true
73
+ end
55
74
  end
56
75
 
57
76
  webpack_assets_compiler ||= WebpackAssetsCompiler.new
@@ -53,8 +53,11 @@ module ReactOnRails
53
53
  def puts_max_iterations_message(loop_count)
54
54
  if loop_count == MAX_TIME_TO_WAIT
55
55
  stale_files = webpack_assets_status_checker.whats_not_up_to_date.join("\n")
56
-
57
- puts <<-MSG
56
+ if stale_files.empty?
57
+ puts "Please check your config value for `config.generated_assets_dirs`."
58
+ puts "We're not finding your generated files for test runs."
59
+ else
60
+ puts <<-MSG
58
61
 
59
62
  Even though we detected the webpack watch processes are running, we found files modified that are
60
63
  not causing a rebuild of your generated files:
@@ -66,6 +69,7 @@ your webpack files: #{webpack_assets_status_checker.client_dir}
66
69
 
67
70
  To be sure, we will now rebuild your generated files.
68
71
  MSG
72
+ end
69
73
  end
70
74
  end
71
75
  end
@@ -24,7 +24,7 @@ https://github.com/shakacode/react_on_rails/blob/master/docs/additional_reading/
24
24
 
25
25
  build_output = `cd client && npm run build:#{type}`
26
26
 
27
- fail "Error in building assets!\n#{build_output}" unless Utils.last_process_completed_successfully?
27
+ raise "Error in building assets!\n#{build_output}" unless Utils.last_process_completed_successfully?
28
28
 
29
29
  puts "Completed building Webpack #{type}-rendering assets."
30
30
  end
@@ -6,16 +6,16 @@ require "fileutils"
6
6
  module ReactOnRails
7
7
  module TestHelper
8
8
  class WebpackAssetsStatusChecker
9
- attr_reader :client_dir, :compiled_dirs
9
+ attr_reader :client_dir, :compiled_dirs, :server_bundle_js_file
10
10
 
11
11
  def initialize(args = {})
12
12
  @compiled_dirs = args.fetch(:compiled_dirs)
13
13
  @client_dir = args.fetch(:client_dir)
14
+ @server_bundle_js_file = args.fetch(:server_bundle_js_file)
14
15
  @last_stale_files = ""
15
16
  end
16
17
 
17
18
  def up_to_date?
18
- # binding.pry
19
19
  return false unless assets_exist?
20
20
  all_compiled_assets.all? do |asset|
21
21
  FileUtils.uptodate?(asset, client_files)
@@ -46,7 +46,11 @@ module ReactOnRails
46
46
  end
47
47
 
48
48
  def all_compiled_assets
49
- make_file_list(make_globs(compiled_dirs)).to_ary
49
+ file_list = make_file_list(make_globs(compiled_dirs)).to_ary
50
+ if file_list && !file_list.empty?
51
+ file_list.delete(server_bundle_js_file)
52
+ end
53
+ file_list
50
54
  end
51
55
 
52
56
  def client_files
@@ -58,12 +62,12 @@ module ReactOnRails
58
62
  end
59
63
 
60
64
  def assets_exist?
61
- all_compiled_assets.to_ary.size > 0
65
+ !all_compiled_assets.empty?
62
66
  end
63
67
 
64
68
  def make_file_list(glob)
65
69
  FileList.new(glob) do |fl|
66
- fl.exclude(%r{/node_modules/})
70
+ fl.exclude(%r{/node_modules})
67
71
  fl.exclude(".DS_Store")
68
72
  fl.exclude(".keep")
69
73
  fl.exclude("thumbs.db")
@@ -22,7 +22,7 @@ module ReactOnRails
22
22
  # We only want to do this if server rendering is enabled.
23
23
  def fail_if_only_running_for_one_type(client_running, server_running)
24
24
  return unless client_running ^ server_running
25
- fail "\n\nError: detected webpack is not running for both types of assets:\n"\
25
+ raise "\n\nError: detected webpack is not running for both types of assets:\n"\
26
26
  "***Webpack Client Process Running?: #{client_running}\n"\
27
27
  "***Webpack Server Process Running?: #{server_running}"
28
28
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ReactOnRails
3
- VERSION = "3.0.6".freeze
3
+ VERSION = "4.0.0.beta.1".freeze
4
4
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-on-rails",
3
- "version": "3.0.6",
3
+ "version": "4.0.0-beta.1",
4
4
  "description": "react-on-rails JavaScript for react_on_rails Ruby gem",
5
5
  "main": "node_package/lib/ReactOnRails.js",
6
6
  "directories": {
@@ -32,7 +32,6 @@ task :release, [:gem_version, :dry_run, :tools_install] do |_t, args|
32
32
  args_hash = args.to_hash
33
33
 
34
34
  is_dry_run = ReactOnRails::Utils.object_to_boolean(args_hash[:dry_run])
35
- should_install_tools = ReactOnRails::Utils.object_to_boolean(args_hash.fetch(:tools_install, true))
36
35
 
37
36
  gem_version = args_hash.fetch(:gem_version, "")
38
37
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react_on_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.6
4
+ version: 4.0.0.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-02 00:00:00.000000000 Z
11
+ date: 2016-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool
@@ -319,6 +319,7 @@ files:
319
319
  - docs/LICENSE
320
320
  - docs/additional_reading/babel.md
321
321
  - docs/additional_reading/heroku_deployment.md
322
+ - docs/additional_reading/hot-reloading-rails-development.md
322
323
  - docs/additional_reading/manual_installation.md
323
324
  - docs/additional_reading/node_dependencies_and_npm.md
324
325
  - docs/additional_reading/optional_configuration.md
@@ -409,6 +410,7 @@ files:
409
410
  - lib/generators/react_on_rails/templates/ruby_linters/ruby-lint.yml.tt
410
411
  - lib/react_on_rails.rb
411
412
  - lib/react_on_rails/configuration.rb
413
+ - lib/react_on_rails/controller.rb
412
414
  - lib/react_on_rails/engine.rb
413
415
  - lib/react_on_rails/git_utils.rb
414
416
  - lib/react_on_rails/prerender_error.rb
@@ -455,9 +457,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
455
457
  version: '0'
456
458
  required_rubygems_version: !ruby/object:Gem::Requirement
457
459
  requirements:
458
- - - ">="
460
+ - - ">"
459
461
  - !ruby/object:Gem::Version
460
- version: '0'
462
+ version: 1.3.1
461
463
  requirements: []
462
464
  rubyforge_project:
463
465
  rubygems_version: 2.4.8