react_on_rails 0.1.1 → 0.1.2

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: c32d5d1549cefdb05c11593b8fc46357c3a2b51a
4
- data.tar.gz: c9a61af04d0b81767c48e155a6cd8af8e9081cc4
3
+ metadata.gz: 6ff4186feb1c1939c00dd049ef22d868aea660f6
4
+ data.tar.gz: 0b5808c38aeb2a3092ec374e6fa8ff2871849f57
5
5
  SHA512:
6
- metadata.gz: ebc8347894681090d81c8e1580aebadaf36fc0465ac9635e054362584c737d22d8d659ec4bd8412bd914cd7adb5b1a3a8cdf880fa5ea6db8ff3a3550d39a21a2
7
- data.tar.gz: ff1e4ab63b241615882224a88666f8c2dc04ea29133881649ba31f539e816a638851924b85c45003e2dfdfd73506336e428f1cdbfbcc36daff7905a7b3286bbf
6
+ metadata.gz: 1c3262b0bb0634626438299e5330e4bd4268a743ddb83f795adfbb2a8e29ed3dc9daf4c987dfca29113c68d66d1daf9e2d5b5277bf59b02cb391dfa28ab6f59e
7
+ data.tar.gz: 0885111f10b06d283bbc39058492a1f5d6e9ff958cc61ba1a4b67ece33a7c78af6006232a1ef380be349d6d7ea8fa2021a022e749574ad9f649fea0107902536
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.eslintignore ADDED
@@ -0,0 +1 @@
1
+ node_modules
data/.eslintrc ADDED
@@ -0,0 +1,16 @@
1
+ ---
2
+ parser: babel-eslint
3
+
4
+ extends: eslint-config-airbnb
5
+
6
+ plugins:
7
+ - react
8
+
9
+ env:
10
+ browser: true
11
+ node: true
12
+
13
+ rules:
14
+ indent: [1, 2, { SwitchCase: 1, VariableDeclarator: 2 }]
15
+ react/sort-comp: 0
16
+ react/jsx-quotes: 0
data/.jscsrc ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "preset": "airbnb",
3
+ "fileExtensions": [".js", ".jsx"],
4
+ "excludeFiles": ["build/**", "node_modules/**"]
5
+ }
data/.rubocop.yml ADDED
@@ -0,0 +1,26 @@
1
+ # This is the configuration used to check the rubocop source code.
2
+ # Check out: https://github.com/bbatsov/rubocop
3
+
4
+ AllCops:
5
+ Include:
6
+ - '**/Rakefile'
7
+ - '**/config.ru'
8
+ Exclude:
9
+ - 'vendor/**/*'
10
+ - 'spec/fixtures/**/*'
11
+ - 'node_modules/**/*'
12
+ - 'db/**/*'
13
+ - 'db/schema.rb'
14
+ - 'db/seeds.rb'
15
+ - 'client/node_modules/**/*'
16
+ - 'bin/**/*'
17
+ - !ruby/regexp /old_and_unused\.rb$/
18
+
19
+ Metrics/LineLength:
20
+ Max: 120
21
+
22
+ Style/StringLiterals:
23
+ EnforcedStyle: double_quotes
24
+
25
+ Style/Documentation:
26
+ Enabled: false
data/.scss-lint.yml ADDED
@@ -0,0 +1,205 @@
1
+ # See http://sass-guidelin.es/#zeros
2
+
3
+ scss_files:
4
+ - 'app/assets/stylesheets/**/*.scss'
5
+ - 'client/assets/stylesheets/**/*.scss'
6
+
7
+ linters:
8
+ # BangFormat:
9
+ # enabled: true
10
+ # space_before_bang: true
11
+ # space_after_bang: false
12
+ #
13
+ # BorderZero:
14
+ # enabled: true
15
+ # convention: zero # or `none`
16
+ #
17
+ ColorKeyword:
18
+ enabled: false
19
+ ColorVariable:
20
+ enabled: false
21
+ #
22
+ # Comment:
23
+ # enabled: true
24
+ #
25
+ # DebugStatement:
26
+ # enabled: true
27
+ #
28
+ # DeclarationOrder:
29
+ # enabled: true
30
+ #
31
+ # DuplicateProperty:
32
+ # enabled: true
33
+ #
34
+ # ElsePlacement:
35
+ # enabled: true
36
+ # style: same_line # or 'new_line'
37
+ #
38
+ # EmptyLineBetweenBlocks:
39
+ # enabled: true
40
+ # ignore_single_line_blocks: true
41
+ #
42
+ # EmptyRule:
43
+ # enabled: true
44
+ #
45
+ # FinalNewline:
46
+ # enabled: true
47
+ # present: true
48
+ #
49
+ HexLength:
50
+ enabled: true
51
+ style: long
52
+
53
+ HexNotation:
54
+ enabled: true
55
+ style: uppercase
56
+ #
57
+ # HexValidation:
58
+ # enabled: true
59
+ #
60
+ IdSelector:
61
+ enabled: true
62
+ #
63
+ # ImportantRule:
64
+ # enabled: true
65
+ #
66
+ # ImportPath:
67
+ # enabled: true
68
+ # leading_underscore: false
69
+ # filename_extension: false
70
+ #
71
+ # Indentation:
72
+ # enabled: true
73
+ # allow_non_nested_indentation: false
74
+ # character: space # or 'tab'
75
+ # width: 2
76
+ #
77
+ LeadingZero:
78
+ enabled: true
79
+ style: include_zero
80
+ #
81
+ # MergeableSelector:
82
+ # enabled: true
83
+ # force_nesting: true
84
+ #
85
+ # NameFormat:
86
+ # enabled: true
87
+ # allow_leading_underscore: true
88
+ # convention: hyphenated_lowercase # or 'camel_case', or 'snake_case', or a regex pattern
89
+ #
90
+ # NestingDepth:
91
+ # enabled: true
92
+ # max_depth: 3
93
+ #
94
+ # PlaceholderInExtend:
95
+ # enabled: true
96
+ #
97
+ # PropertyCount:
98
+ # enabled: false
99
+ # include_nested: false
100
+ # max_properties: 10
101
+ #
102
+ # PropertyUnits:
103
+ # enabled: true
104
+ # global: [
105
+ # 'ch', 'em', 'ex', 'rem', # Font-relative lengths
106
+ # 'cm', 'in', 'mm', 'pc', 'pt', 'px', 'q', # Absolute lengths
107
+ # 'vh', 'vw', 'vmin', 'vmax', # Viewport-percentage lengths
108
+ # 'deg', 'grad', 'rad', 'turn', # Angle
109
+ # 'ms', 's', # Duration
110
+ # 'Hz', 'kHz', # Frequency
111
+ # 'dpi', 'dpcm', 'dppx', # Resolution
112
+ # '%', # Other
113
+ # ]
114
+ # properties: {}
115
+ #
116
+ # PropertySortOrder:
117
+ # enabled: true
118
+ # ignore_unspecified: false
119
+ # separate_groups: false
120
+ #
121
+ # PropertySpelling:
122
+ # enabled: true
123
+ # extra_properties: []
124
+ #
125
+ # QualifyingElement:
126
+ # enabled: true
127
+ # allow_element_with_attribute: false
128
+ # allow_element_with_class: false
129
+ # allow_element_with_id: false
130
+ #
131
+ # SelectorDepth:
132
+ # enabled: true
133
+ # max_depth: 3
134
+ #
135
+ # SelectorFormat:
136
+ # enabled: true
137
+ # convention: hyphenated_lowercase # or 'strict_BEM', or 'hyphenated_BEM', or 'snake_case', or 'camel_case', or a regex pattern
138
+ #
139
+ # Shorthand:
140
+ # enabled: true
141
+ # allowed_shorthands: [1, 2, 3]
142
+ #
143
+ # SingleLinePerProperty:
144
+ # enabled: true
145
+ # allow_single_line_rule_sets: true
146
+ #
147
+ # SingleLinePerSelector:
148
+ # enabled: true
149
+ #
150
+ # SpaceAfterComma:
151
+ # enabled: true
152
+ #
153
+ # SpaceAfterPropertyColon:
154
+ # enabled: true
155
+ # style: one_space # or 'no_space', or 'at_least_one_space', or 'aligned'
156
+ #
157
+ # SpaceAfterPropertyName:
158
+ # enabled: true
159
+ #
160
+ # SpaceBeforeBrace:
161
+ # enabled: true
162
+ # style: space # or 'new_line'
163
+ # allow_single_line_padding: false
164
+ #
165
+ # SpaceBetweenParens:
166
+ # enabled: true
167
+ # spaces: 0
168
+ #
169
+ # StringQuotes:
170
+ # enabled: true
171
+ # style: single_quotes # or double_quotes
172
+ #
173
+ # TrailingSemicolon:
174
+ # enabled: true
175
+ #
176
+ # TrailingZero:
177
+ # enabled: false
178
+ #
179
+ # UnnecessaryMantissa:
180
+ # enabled: true
181
+ #
182
+ # UnnecessaryParentReference:
183
+ # enabled: true
184
+ #
185
+ # UrlFormat:
186
+ # enabled: true
187
+ #
188
+ # UrlQuotes:
189
+ # enabled: true
190
+ #
191
+ # VariableForProperty:
192
+ # enabled: false
193
+ # properties: []
194
+ #
195
+ # VendorPrefix:
196
+ # enabled: true
197
+ # identifier_list: base
198
+ # additional_identifiers: []
199
+ # excluded_identifiers: []
200
+ #
201
+ # ZeroUnit:
202
+ # enabled: true
203
+ #
204
+ # Compass::*:
205
+ # enabled: false
data/.travis.yml CHANGED
@@ -1,4 +1,12 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.2
4
- before_install: gem install bundler -v 1.10.5
3
+ - 2.2.2
4
+ gemfile:
5
+ - spec/dummy/Gemfile
6
+ install: bundle install
7
+ script:
8
+ - rake run_rspec:gem
9
+ - rake run_rspec:dummy
10
+ notifications:
11
+ slack:
12
+ secure: LfcUk4AJ4vAxWwRIyw4tFh8QNbYefMwfG/oLfsN3CdRMWMOtCOHR1GGsRhAOlfVVJ/FvHqVqWj5gK7z7CaO5Uvl7rD3/zJ8QzExKx/iH9yWj55iIPuKLzwFNnBwRpFW/cqyU2lFPPRxGD50BUn3c+qybkuSqtKZ6qtTowwqlxLa5iyM3N95aZp7MEIKCP7cPcnHfLbJyP8wBpotp/rtw62eXM2HIRJJwgjcp+n+My7VFR9DnBXNFf6R91aZHM4U4cHHDbu15HFtH8honVrzK1JQdyqMNHga+j04dFuaS7z9Q369/hsELMOBp/227+Pz7ZRfWZFK4UASguOvyeX7RmGTRpTuWLm1XJeUzfsPZVROecaSVQBve+U7F12yKqilt97QlvRXn2EGyBILqvxtFNNR4S9kgAf72/6EFgiM1TKq7i9zy6lVOnagU2+7amq7UeopX1uoFsUfNKMR7YbgV1WjF0IK95UP0b0/7ZOJlPYgi5zzkQi129qAFWSMmxGk+ZpsttHh/tjJtvAh0A3mHq/zb5w4ub/MbSyZqeDUNgGj72QArOWUFSAStQT1ybsVLeDoKPgOvVq7OV1D64rpcHjBXcqOCit8tDZ+TqkFhcYJo2cITSaqE4zJXn+4F5s7So5O8CyfKYQq+kFJCooYGmfgTUckJpGl7eIvKmL4TN9Q=
data/Dockerfile ADDED
@@ -0,0 +1,14 @@
1
+ FROM ruby:2.2.3
2
+ MAINTAINER Dylan Grafmyre <dylan@shakacode.com>
3
+
4
+ RUN mkdir -p /app
5
+ WORKDIR /app/
6
+ # Setup container for linting with ruby and npm
7
+ RUN gem install rubocop ruby-lint scss_lint
8
+ RUN curl --silent --location https://deb.nodesource.com/setup_0.12 | bash -
9
+ RUN apt-get install -y nodejs
10
+ RUN npm install -g eslint \
11
+ eslint-config-airbnb \
12
+ eslint-plugin-react \
13
+ babel-eslint \
14
+ jscs
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
+ [![Build Status](https://travis-ci.org/shakacode/react_on_rails.svg?branch=master)](https://travis-ci.org/shakacode/react_on_rails)
2
+ [![Coverage Status](https://coveralls.io/repos/shakacode/react_on_rails/badge.svg?branch=master&service=github)](https://coveralls.io/github/shakacode/react_on_rails?branch=master)
3
+ [![Dependency Status](https://gemnasium.com/shakacode/react_on_rails.svg)](https://gemnasium.com/shakacode/react_on_rails)
1
4
  # React On Rails
2
5
 
3
- Published: https://rubygems.org/gems/react_on_rails
6
+ Gem Published: https://rubygems.org/gems/react_on_rails
4
7
 
5
8
  See [Action Plan for v1.0](https://github.com/shakacode/react_on_rails/issues/1)
6
9
 
@@ -16,108 +19,242 @@ Supports:
16
19
  6. Server side rendering with fragment caching
17
20
  7. react-router for client side rendering (and maybe server side eventually)
18
21
 
19
- # Authors
20
- The Shaka Code team!
22
+ # Links
23
+ 1. https://github.com/justin808/react-webpack-rails-tutorial/ See https://github.com/shakacode/react-webpack-rails-tutorial/pull/84 for how we integrated it!
24
+ 2. http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/
25
+ 3. http://forum.railsonmaui.com
26
+ 5. If this project is interesting to you, email me at justin@shakacode.com. We're looking for great
27
+ developers that want to work with Rails + React with a distributed, worldwide team, for our own
28
+ products, client work, and open source.
21
29
 
22
- 1. [Justin Gordon](https://github.com/justin808/)
23
- 2. [Samnang Chhun](https://github.com/samnang)
24
- 3. [Alex Fedoseev](https://github.com/alexfedoseev)
30
+ ## Application Installation
25
31
 
26
- And based on the work of the [react-rails gem](https://github.com/reactjs/react-rails)
32
+ Add these lines to your application's Gemfile, sustituting your preferable JavaScript engine.
27
33
 
28
- # Key Info
29
- Currently being implemented in 3 production projects (not yet live).
34
+ ```ruby
35
+ gem "react_on_rails"
36
+ gem "therubyracer"
37
+ ```
30
38
 
31
- 1. https://github.com/justin808/react-webpack-rails-tutorial/
32
- 2. http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/
33
- 3. http://forum.railsonmaui.com
34
- 4. Lots of work to do in terms of docs, tests
35
- 5. If this project is interesting to you, email me at justin@shakacode.com. We're looking for great
36
- developers that want to work with Rails + React with a distributed, worldwide team.
39
+ And then execute:
37
40
 
41
+ $ bundle
42
+
43
+ ## Usage
44
+
45
+ *See section below titled "Try it out"*
46
+
47
+ ### Helper Method
48
+ The main API is a helper:
49
+
50
+ ```ruby
51
+ react_component(component_name, props = {}, options = {})
52
+ ```
53
+
54
+ Params are:
55
+
56
+ * **react_component_name**: can be a React component, created using a ES6 class, or React.createClass,
57
+ or a `generator function` that returns a React component
58
+
59
+ using ES6
60
+ ```javascript
61
+ let MyReactComponentApp = (props) => <MyReactComponent {...props}/>;
62
+ ```
63
+
64
+ or using ES5
65
+ ```javascript
66
+ var MyReactComponentApp = function(props) { return <YourReactComponent {...props}/>; }
67
+ ```
68
+ Exposing the react_component_name is necessary to both a plain ReactComponent as well as
69
+ a generator:
70
+ For client rendering, expose the react_component_name on window:
71
+
72
+ ```javascript
73
+ window.MyReactComponentApp = MyReactComponentApp;
74
+ ```
75
+ For server rendering, export the react_component_name on global:
76
+ ```javascript
77
+ global.MyReactComponentApp = MyReactComponentApp;
78
+ ```
79
+ See `spec/dummy/client/app/startup/serverGlobals.jsx` and
80
+ `spec/dummy/client/app/startup/ClientApp.jsx` for examples of this.
81
+
82
+ * **props**: Ruby Hash which contains the properties to pass to the react object
83
+
84
+ * **options:**
85
+ * **generator_function**: <true/false> default is false, set to true if you want to use a generator function rather than a React Component.
86
+ * **prerender**: <true/false> set to false when debugging!
87
+ * **trace**: <true/false> set to true to print additional debugging information in the browser default is true for development, off otherwise
88
+ * **replay_console**: <true/false> Default is true. False will disable echoing server rendering logs, which can make troubleshooting server rendering difficult.
89
+
90
+ ## JavaScript
91
+
92
+ 1. Configure your webpack configuration to create the file used for server rendering if you plan to
93
+ do server rendering.
94
+ 2. Follow the examples in `spec/dummy/client/app/startup/clientGlobals.jsx` to expose your react components
95
+ for client side rendering.
96
+ ```ruby
97
+ import HelloWorld from '../components/HelloWorld';
98
+ window.HelloWorld = HelloWorld;
99
+ ```
100
+ 3. Follow the examples in `spec/dummy/client/app/startup/serverGlobals.jsx` to expose your react components
101
+ for client side rendering.
102
+ ```ruby
103
+ import HelloWorld from '../components/HelloWorld';
104
+ global.HelloWorld = HelloWorld;
105
+ ```
106
+
107
+ ## Optional Configuration
108
+
109
+ Create a file `config/react_on_rails.rb` to override any defaults. If you don't specify this file,
110
+ the default options are below.
111
+
112
+ The `server_bundle_js_file` must correspond to the bundle you want to use for server rendering.
38
113
 
39
- # Try it out!
114
+ ```ruby
115
+ # Shown below are the defaults for configuration
116
+ ReactOnRails.configure do |config|
117
+ # Client bundles are configured in application.js
118
+ # Server bundle is a single file for all server rendering of components.
119
+ config.server_bundle_js_file = "app/assets/javascripts/generated/server.js" # This is the default
120
+
121
+ # Below options can be overriden by passing to the helper method.
122
+ config.prerender = false # default is false
123
+ config.generator_function = false # default is false, meaning that you expose ReactComponents directly
124
+ config.trace = Rails.env.development? # default is true for development, off otherwise
125
+
126
+ # For server rendering. This can be set to false so that server side messages are discarded.
127
+ config.replay_console = true # Default is true. Be cautious about turning this off.
128
+ end
129
+ ```
130
+
131
+ # Try it out in the simple sample app
40
132
  Contributions and pull requests welcome!
41
133
 
42
- 1. Setup and run the test app. There's no database.
134
+ 1. Setup and run the test app in `spec/dummy`. Note, there's no database.
43
135
  ```bash
44
136
  cd spec/dummy
45
137
  bundle
46
138
  npm i
47
- foreman start
48
- ```
139
+ foreman start
140
+ ```
49
141
  2. Caching is turned for development mode. Open the console and run `Rails.cache.clear` to clear
50
142
  the cache. Note, even if you stop the server, you'll still have the cache entries around.
51
143
  3. Visit http://localhost:3000
52
144
  4. Notice that the first time you hit the page, you'll see a message that server is rendering.
53
145
  See `spec/dummy/app/views/pages/index.html.erb:17` for the generation of that message.
146
+ 5. Look at the layouts in `spec/dummy/app/views/pages` for samples of usage.
54
147
  5. Open up the browser console and see some tracing.
55
148
  6. Open up the source for the page and see the server rendered code.
56
- 7. If you want to turn off server caching, run the server like:
149
+ 7. If you want to turn off server caching, run the server like:
57
150
  `export RAILS_USE_CACHE=N && foreman start`
58
151
  8. If you click back and forth between the about and react page links, you can see the rails console
59
152
  log as well as the browser console to see what's going on with regards to server rendering and
60
153
  caching.
61
154
 
62
155
  # Key Tips
63
- 1. See sample app in `spec/dummy` for how to set this up.
156
+ 1. See sample app in `spec/dummy` for how to set this up. See note below on ensuring you
157
+ **DO NOT RUN `rails s` and instead run `foreman start`.
158
+ 2. Test out the different options and study the JSX samples in `spec/dummy/client/app/startup`.
159
+ 3. Experiment with changing the settings on the `render_component` helper calls in the ERB files.
64
160
  2. The file used for server rendering is hard coded as `generated/server.js`
65
161
  (assets/javascripts/generated/server.js).
66
- 3. If you're only doing client rendering, you still *MUST* create an empty version of this file. This
67
- will soon change so that this is not necessary.
68
- 3. The default for rendering right now is `prerender: false`. **NOTE:** Server side rendering does
69
- not work for some components, namely react-router, that use an async setup for server rendering.
70
- You can configure the default for prerender in your config.
71
- 4. The API for objects exposed differs from the react-rails gem in that you expose a function that
72
- returns a react component. We'll be changing that to take either a function or a React component.
73
-
74
- # Example Configuration, config/react_on_rails.rb
162
+ 3. The default for rendering right now is `prerender: false`. **NOTE:** Server side rendering does
163
+ not work for some components, namely react-router, that use an async setup for server rendering.
164
+ You can configure the default for prerender in your config.
165
+ 4. You can expose either a React component or a function that returns a React component. If you
166
+ wish to create a React component via a function, rather than simply props, then you need to set
167
+ the property "generator" on that function to true. When that is done, the function is invoked
168
+ with a single parameter of "props", and that function should return a React element.
169
+ 5. Be sure you can first render your react component client only before you try to debug server
170
+ rendering!
171
+ 4. Open up the HTML source and take a look at the generated HTML and the JavaScript to see what's
172
+ going on under the covers. Not that when server rendering is turned on, then you'll see the
173
+ server rendered react components. When server rendering is turned off, then you'll only see
174
+ the `div` element where the inline JavaScript will render the component. You might also notice
175
+ how the props you pass (a Ruby Hash) becomes inline JavaScript on the HTML page.
176
+
177
+ TODO: Check if this is true still: If you're only doing client rendering, you still *MUST* create an empty version of this file. This
178
+ will soon change so that this is not necessary.
179
+
180
+ ## JavaScript Runtime Configuration
181
+ See this [discussion on JavaScript performance](https://github.com/shakacode/react_on_rails/issues/21).
182
+ The net result is that you want to add this line to your Gemfile to get therubyracer as your default
183
+ JavaScript engine.
184
+
75
185
  ```ruby
76
- ReactOnRails.configure do |config|
77
- config.bundle_js_file = "app/assets/javascripts/generated/server.js" # This is the default
78
- config.prerender = true # default is false
79
- end
186
+ gem "therubyracer"
80
187
  ```
81
188
 
82
-
83
189
  ## References
84
190
  * [Making the helper for server side rendering work with JS created by Webpack] (https://github.com/reactjs/react-rails/issues/301#issuecomment-133098974)
85
191
  * [Add Demonstration of Server Side Rendering](https://github.com/justin808/react-webpack-rails-tutorial/issues/2)
86
192
  * [Charlie Marsh's article "Rendering React Components on the Server"](http://www.crmarsh.com/react-ssr/)
87
193
  * [Node globals](https://nodejs.org/api/globals.html#globals_global)
88
194
 
89
- ## Installation
90
195
 
91
- Add this line to your application's Gemfile:
196
+ ## Development Setup for Gem Contributors
92
197
 
93
- ```ruby
94
- gem 'react_on_rails'
95
- ```
198
+ ### Initial Setup
199
+ After checking out the repo, making sure you have rvm and nvm setup (setup ruby and node),
200
+ cd to `spec/dummy` and run `bin/setup` to install dependencies.
201
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
96
202
 
97
- And then execute:
203
+ ### Starting the Dummy App
204
+ To run the test app, it's **CRITICAL** to not just run `rails s`. You have to run `foreman start`.
205
+ If you don't do this, then `webpack` will not generate a new bundle,
206
+ and you will be seriously confused when you change JavaScript and the app does not change.
98
207
 
99
- $ bundle
208
+ ### Install and Release
209
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version,
210
+ update the version number in `version.rb`, and then run `bundle exec rake release`,
211
+ which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
100
212
 
101
- Or install it yourself as:
213
+ ### RSpec Testing
214
+ Run `rake` for testing the gem and `spec/dummy`. Otherwise, the `rspec` command only works for testing within `spec/dummy`.
102
215
 
103
- $ gem install react_on_rails
216
+ If you run `rspec` at the top level, you'll see this message: `require': cannot load such file -- rails_helper (LoadError)`
104
217
 
105
- ## Usage
218
+ ### Debugging
219
+ Start the sample app like this for some debug printing:
220
+ ```bash
221
+ TRACE_REACT_ON_RAILS=true && foreman start
222
+ ```
106
223
 
107
- PENDING. See `spec/dummy` for the sample app.
224
+ ### Linting
225
+ All linting is performed from the docker container. You will need docker and docker-compose installed
226
+ locally to lint code changes via the lint container.
108
227
 
109
- ## Development
228
+ * [Install Docker Toolbox for Mac](https://www.docker.com/toolbox)
229
+ * [Install Docker Compose for Linux](https://docs.docker.com/compose/install/)
110
230
 
111
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
231
+ Once you have docker and docker-compose running locally, run `docker-compose build lint`. This will build
232
+ the `reactonrails_lint` docker image and docker-compose `lint` container. The inital build is slow,
233
+ but after the install, startup is very quick.
112
234
 
113
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
235
+ ### Linting Commands
236
+ Run `rake -D docker` to see all docker linting commands for rake. `rake docker` will run all linters.
237
+ For individual rake linting commands please refer to `rake -D docker` for the list.
238
+ You can run specfic linting for directories or files by using `docker-compose run lint rubocop (file path or directory)`, etc.
239
+ `docker-compose run lint /bin/bash` sets you up to run from the container command line.
114
240
 
115
241
  ## Contributing
116
242
 
117
243
  Bug reports and pull requests are welcome on GitHub at https://github.com/shakacode/react_on_rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
118
244
 
119
-
120
245
  ## License
121
246
 
122
247
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
123
248
 
249
+ ## Updating New Versions of the Gem
250
+
251
+ See https://github.com/svenfuchs/gem-release
252
+
253
+ # Authors
254
+ The Shaka Code team!
255
+
256
+ 1. [Justin Gordon](https://github.com/justin808/)
257
+ 2. [Samnang Chhun](https://github.com/samnang)
258
+ 3. [Alex Fedoseev](https://github.com/alexfedoseev)
259
+
260
+ And based on the work of the [react-rails gem](https://github.com/reactjs/react-rails)
data/Rakefile CHANGED
@@ -1,6 +1,91 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require "fileutils"
2
+
3
+ namespace :run_rspec do
4
+ desc "Run RSpec for top level only"
5
+ task :gem do
6
+ sh %{ rspec --exclude-pattern "spec/dummy/**/*_spec.rb" spec }
7
+ end
8
+
9
+ desc "Run RSpec for spec/dummy only"
10
+ task :dummy do
11
+ sh %{ cd spec/dummy && rspec }
12
+ end
13
+
14
+ task run_rspec: [:gem, :dummy] do
15
+ puts "Completed all RSpec tests"
16
+ end
17
+ end
18
+ desc "Runs all tests. Run `rake -D run_rspec` to see all available test options"
19
+ task run_rspec: ["run_rspec:run_rspec"]
20
+
21
+ task default: :run_rspec
22
+
23
+ namespace :lint do
24
+
25
+ desc "Run Rubocop as shell"
26
+ task :rubocop do
27
+ sh "rubocop ."
28
+ end
29
+
30
+ desc "Run ruby-lint as shell"
31
+ task :ruby do
32
+ sh "ruby-lint app spec lib"
33
+ end
34
+
35
+ desc "Run scss-lint as shell"
36
+ task :scss do
37
+ sh "scss-lint ."
38
+ end
39
+
40
+ desc "Run eslint as shell"
41
+ task :eslint do
42
+ sh "eslint . --ext .jsx and .js"
43
+ end
44
+
45
+ desc "Run jscs from shell"
46
+ task :jscs do
47
+ sh "jscs ."
48
+ end
49
+
50
+ task lint: [:eslint, :rubocop, :ruby, :jscs, :scss] do
51
+ puts "Completed all linting"
52
+ end
53
+ end
54
+ desc "Runs all linters. Run `rake -D lint` to see all available lint options"
55
+ task lint: ["lint:lint"]
56
+
57
+ namespace :docker do
58
+ desc "Run Rubocop linter from docker"
59
+ task :rubocop do
60
+ sh "docker-compose run lint rake lint:rubocop"
61
+ end
62
+
63
+ desc "Run ruby-lint linter from docker"
64
+ task :ruby do
65
+ sh "docker-compose run lint rake lint:ruby"
66
+ end
67
+
68
+ desc "Run scss-lint linter from docker"
69
+ task :scss do
70
+ sh"docker-compose run lint rake lint:scss"
71
+ end
72
+
73
+ desc "Run eslint linter from docker"
74
+ task :eslint do
75
+ sh "docker-compose run lint rake lint:eslint"
76
+ end
77
+
78
+ desc "Run jscs linter from docker"
79
+ task :jscs do
80
+ sh "docker-compose run lint rake lint:jscs"
81
+ end
82
+ desc "Run all linting from docker"
83
+ task :lint do
84
+ sh "docker-compose run lint rake lint"
85
+ end
86
+ end
87
+
88
+ desc "Runs all linters from docker. Run `rake -D docker` to see all available lint options"
89
+ task docker: ["docker:lint"]
3
90
 
4
- RSpec::Core::RakeTask.new(:spec)
5
91
 
6
- task :default => :spec
@@ -2,132 +2,198 @@ require 'react_on_rails/react_renderer'
2
2
 
3
3
  module ReactOnRailsHelper
4
4
 
5
- # component_name: React component name
5
+ # react_component_name: can be a React component, created using a ES6 class, or
6
+ # React.createClass, or a
7
+ # `generator function` that returns a React component
8
+ # using ES6
9
+ # let MyReactComponentApp = (props) => <MyReactComponent {...props}/>;
10
+ # or using ES5
11
+ # var MyReactComponentApp = function(props) { return <YourReactComponent {...props}/>; }
12
+ # Exposing the react_component_name is necessary to both a plain ReactComponent as well as
13
+ # a generator:
14
+ # For client rendering, expose the react_component_name on window:
15
+ # window.MyReactComponentApp = MyReactComponentApp;
16
+ # For server rendering, export the react_component_name on global:
17
+ # global.MyReactComponentApp = MyReactComponentApp;
18
+ # See spec/dummy/client/app/startup/serverGlobals.jsx and
19
+ # spec/dummy/client/app/startup/ClientApp.jsx for examples of this
6
20
  # props: Ruby Hash which contains the properties to pass to the react object
7
21
  #
8
- # Naming Conventions:
9
- # Suppose your component is named "App" (can be anything)
10
- # 1. Inside app/startup/ServerApp.jsx, setup the component for server rendering. This is used by
11
- # the global exports in step 2
12
- # 2. Component_name is changed to CamelizedUpper for the exposed component,
13
- # so we have App as the exposed global (see app/startup/serverGlobals.jsx)
14
- # 3. Inside app/startup/ClientApp.jsx, you want to export a function that generates
15
- # your component, and when you generate the component, you must use this naming convention
16
- # to get the data.
17
- # App(__appData__)
18
- # That way it gets the data you pass from the Rails helper.
19
- #
20
22
  # options:
21
- # prerender: <true/false> defaults to true
22
- # trace: <true/false> defaults to false, set to true to print additional info
23
+ # generator_function: <true/false> default is false, set to true if you want to use a
24
+ # generator function rather than a React Component.
25
+ # prerender: <true/false> set to false when debugging!
26
+ # trace: <true/false> set to true to print additional debugging information in the browser
27
+ # default is true for development, off otherwise
28
+ # replay_console: <true/false> Default is true. False will disable echoing server rendering
29
+ # logs, which can make troubleshooting server rendering difficult.
23
30
  def react_component(component_name, props = {}, options = {})
31
+ # Create the JavaScript and HTML to allow either client or server rendering of the
32
+ # react_component.
33
+ #
24
34
  # Create the JavaScript setup of the global to initialize the client rendering
25
35
  # (re-hydrate the data). This enables react rendered on the client to see that the
26
36
  # server has already rendered the HTML.
27
- @react_component_index ||= 0
28
- prerender = options.fetch(:prerender) { ReactOnRails.configuration.prerender }
29
- trace = options.fetch(:trace, false)
30
-
31
- dataVariable = "__#{component_name.camelize(:lower)}Data#{@react_component_index}__"
32
- reactComponent = component_name.camelize
33
- domId = "#{component_name}-react-component-#{@react_component_index}"
34
- @react_component_index += 1
35
-
37
+ # We use this react_component_index in case we have the same component multiple times on the page.
38
+ react_component_index = next_react_component_index
39
+ react_component_name = component_name.camelize # Not sure if we should be doing this (JG)
40
+ dom_id = "#{component_name}-react-component-#{react_component_index}"
41
+
42
+ # Setup the page_loaded_js, which is the same regardless of prerendering or not!
43
+ # The reason is that React is smart about not doing extra work if the server rendering did its job.
44
+ data_variable_name = "__#{component_name.camelize(:lower)}Data#{react_component_index}__"
36
45
  turbolinks_loaded = Object.const_defined?(:Turbolinks)
37
- install_render_events = turbolinks_loaded ? turbolinks_bootstrap(domId) : non_turbolinks_bootstrap
38
-
46
+ install_render_events = turbolinks_loaded ? turbolinks_bootstrap(dom_id) : non_turbolinks_bootstrap
39
47
  page_loaded_js = <<-JS
40
- (function() {
41
- window.#{dataVariable} = #{props.to_json};
42
- #{define_render_if_dom_node_present(reactComponent, dataVariable, domId, trace)}
43
- #{install_render_events}
44
- })();
48
+ (function() {
49
+ window.#{data_variable_name} = #{props.to_json};
50
+ #{define_render_if_dom_node_present(react_component_name, data_variable_name, dom_id, trace(options), generator_function(options))}
51
+ #{install_render_events}
52
+ })();
45
53
  JS
46
54
 
47
55
  data_from_server_script_tag = javascript_tag(page_loaded_js)
48
56
 
49
57
  # Create the HTML rendering part
50
- if prerender
58
+ server_rendered_html =
59
+ server_rendered_react_component_html(options, props, react_component_name)
60
+
61
+ rendered_output = content_tag(:div,
62
+ server_rendered_html,
63
+ id: dom_id)
64
+
65
+ # IMPORTANT: Ensure that we mark string as html_safe to avoid escaping.
66
+ <<-HTML.html_safe
67
+ #{data_from_server_script_tag}
68
+ #{rendered_output}
69
+ HTML
70
+ end
71
+
72
+ def next_react_component_index
73
+ @react_component_index ||= -1
74
+ @react_component_index += 1
75
+ end
76
+
77
+ def server_rendered_react_component_html(options, props, react_component_name)
78
+ if prerender(options)
51
79
  render_js_expression = <<-JS
52
- renderReactComponent(this.#{reactComponent}, #{props.to_json})
80
+ (function(React) {
81
+ var reactElement = #{render_js_react_element(react_component_name, props.to_json, generator_function(options))};
82
+ return React.renderToString(reactElement);
83
+ })(this.React);
53
84
  JS
54
- server_rendered_react_component_html = render_js(render_js_expression)
85
+ # create the server generated html of the react component with props
86
+ options[:react_component_name] = react_component_name
87
+ server_rendered_react_component_html =
88
+ render_js(render_js_expression, options)
55
89
  else
56
90
  server_rendered_react_component_html = ""
57
91
  end
58
-
59
- rendered_output = content_tag(:div,
60
- server_rendered_react_component_html,
61
- id: domId)
62
-
63
- <<-HTML.strip_heredoc.html_safe
64
- #{data_from_server_script_tag}
65
- #{rendered_output}
66
- HTML
92
+ server_rendered_react_component_html
67
93
  end
68
94
 
69
95
  # Takes javascript code and returns the output from it. This is called by react_component, which
70
96
  # sets up the JS code for rendering a react component.
71
97
  # This method could be used by itself to render the output of any javascript that returns a
72
98
  # string of proper HTML.
73
- def render_js(js_expression)
74
- ReactOnRails::ReactRenderer.new.render_js(js_expression).html_safe
99
+ def render_js(js_expression, options = {})
100
+ ReactOnRails::ReactRenderer.new(options).render_js(js_expression,
101
+ options).html_safe
75
102
  end
76
103
 
77
104
  private
78
105
 
79
- def debug_js(react_component, data_variable, dom_id, trace)
106
+ def trace(options)
107
+ options.fetch(:trace) { ReactOnRails.configuration.trace }
108
+ end
109
+
110
+ def generator_function(options)
111
+ options.fetch(:generator_function) { ReactOnRails.configuration.generator_function }
112
+ end
113
+
114
+ def prerender(options)
115
+ options.fetch(:prerender) { ReactOnRails.configuration.prerender }
116
+ end
117
+
118
+ def debug_js(react_component_name, data_variable, dom_id, trace)
80
119
  if trace
81
- <<-JS.strip_heredoc
82
- console.log("CLIENT SIDE RENDERED #{react_component} with dataVariable #{data_variable} to dom node with id: #{dom_id}");
120
+ <<-JS
121
+ console.log("CLIENT SIDE RENDERED #{react_component_name} with data_variable #{data_variable} to dom node with id: #{dom_id}");
83
122
  JS
84
123
  else
85
124
  ""
86
125
  end
87
126
  end
88
127
 
89
- def define_render_if_dom_node_present(react_component, data_variable, dom_id, trace)
90
- <<-JS.strip_heredoc
91
- var renderIfDomNodePresent = function() {
92
- var domNode = document.getElementById('#{dom_id}');
93
- if (domNode) {
94
- #{debug_js(react_component, data_variable, dom_id, trace)}
95
- var reactComponent = #{react_component}(#{data_variable});
96
- React.render(reactComponent, domNode);
97
- }
98
- }
128
+ # react_component_name: See app/helpers/react_on_rails_helper.rb:5
129
+ # props_string: is either the variable name used to hold the props (client side) or the
130
+ # stringified hash of props from the Ruby server side. In terms of the view helper, one is
131
+ # simply passing in the Ruby Hash of props.
132
+ #
133
+ # Returns the JavaScript code to generate a React element.
134
+ def render_js_react_element(react_component_name, props_string, generator_function)
135
+ # "this" is defined by the calling context which is "global" in the execJs
136
+ # environment or window in the client side context.
137
+ js_create_element = if generator_function
138
+ "#{react_component_name}(props)"
139
+ else
140
+ "React.createElement(#{react_component_name}, props)"
141
+ end
142
+
143
+ <<-JS
144
+ (function(React) {
145
+ var props = #{props_string};
146
+ return #{js_create_element};
147
+ })(this.React);
148
+ JS
149
+ end
150
+
151
+ def define_render_if_dom_node_present(react_component_name, data_variable, dom_id, trace, generator_function)
152
+ inner_js_code = <<-JS_CODE
153
+ var domNode = document.getElementById('#{dom_id}');
154
+ if (domNode) {
155
+ #{debug_js(react_component_name, data_variable, dom_id, trace)}
156
+ var reactElement = #{render_js_react_element(react_component_name, data_variable, generator_function)};
157
+ React.render(reactElement, domNode);
158
+ }
159
+ JS_CODE
160
+
161
+ <<-JS
162
+ var renderIfDomNodePresent = function() {
163
+ #{ReactOnRails::ReactRenderer.wrap_code_with_exception_handler(inner_js_code, react_component_name)}
164
+ }
99
165
  JS
100
166
  end
101
167
 
102
168
  def non_turbolinks_bootstrap
103
- <<-JS.strip_heredoc
104
- document.addEventListener("DOMContentLoaded", function(event) {
105
- console.log("DOMContentLoaded event fired");
106
- renderIfDomNodePresent();
107
- });
169
+ <<-JS
170
+ document.addEventListener("DOMContentLoaded", function(event) {
171
+ console.log("DOMContentLoaded event fired");
172
+ renderIfDomNodePresent();
173
+ });
108
174
  JS
109
175
  end
110
176
 
111
177
  def turbolinks_bootstrap(dom_id)
112
- <<-JS.strip_heredoc
113
- var turbolinksInstalled = typeof(Turbolinks) !== 'undefined';
114
- if (!turbolinksInstalled) {
115
- console.warn("WARNING: NO TurboLinks detected in JS, but it's in your Gemfile");
116
- #{non_turbolinks_bootstrap}
117
- } else {
118
- function onPageChange(event) {
119
- var removePageChangeListener = function() {
120
- document.removeEventListener("page:change", onPageChange);
121
- document.removeEventListener("page:before-unload", removePageChangeListener);
122
- var domNode = document.getElementById('#{dom_id}');
123
- React.unmountComponentAtNode(domNode);
124
- };
125
- document.addEventListener("page:before-unload", removePageChangeListener);
126
-
127
- renderIfDomNodePresent();
128
- }
129
- document.addEventListener("page:change", onPageChange);
130
- }
178
+ <<-JS
179
+ var turbolinksInstalled = typeof(Turbolinks) !== 'undefined';
180
+ if (!turbolinksInstalled) {
181
+ console.warn("WARNING: NO TurboLinks detected in JS, but it's in your Gemfile");
182
+ #{non_turbolinks_bootstrap}
183
+ } else {
184
+ function onPageChange(event) {
185
+ var removePageChangeListener = function() {
186
+ document.removeEventListener("page:change", onPageChange);
187
+ document.removeEventListener("page:before-unload", removePageChangeListener);
188
+ var domNode = document.getElementById('#{dom_id}');
189
+ React.unmountComponentAtNode(domNode);
190
+ };
191
+ document.addEventListener("page:before-unload", removePageChangeListener);
192
+
193
+ renderIfDomNodePresent();
194
+ }
195
+ document.addEventListener("page:change", onPageChange);
196
+ }
131
197
  JS
132
198
  end
133
199
  end
@@ -0,0 +1,5 @@
1
+ lint:
2
+ build: .
3
+ working_dir: /app/
4
+ volumes:
5
+ - '.:/app/'
@@ -5,17 +5,24 @@ module ReactOnRails
5
5
 
6
6
  def self.configuration
7
7
  @configuration ||= Configuration.new(
8
- bundle_js_file: "app/assets/javascripts/generated/server.js",
9
- prerender: false
8
+ server_bundle_js_file: "app/assets/javascripts/generated/server.js",
9
+ prerender: false,
10
+ replay_console: true,
11
+ generator_function: false,
12
+ trace: Rails.env.development?
10
13
  )
11
14
  end
12
15
 
13
16
  class Configuration
14
- attr_accessor :bundle_js_file, :prerender
17
+ attr_accessor :server_bundle_js_file, :prerender, :replay_console, :generator_function, :trace
15
18
 
16
- def initialize(bundle_js_file:, prerender:)
17
- self.bundle_js_file = bundle_js_file
19
+ def initialize(server_bundle_js_file: nil, prerender: nil, replay_console: nil,
20
+ generator_function: nil, trace: nil)
21
+ self.server_bundle_js_file = server_bundle_js_file
18
22
  self.prerender = prerender
23
+ self.replay_console = replay_console
24
+ self.generator_function = generator_function
25
+ self.trace = Rails.env.development?
19
26
  end
20
27
  end
21
28
  end
@@ -1,41 +1,134 @@
1
+ # Kudos to react-rails for how to do the polyfill of the console!
2
+ # https://github.com/reactjs/react-rails/blob/master/lib/react/server_rendering/sprockets_renderer.rb
3
+
1
4
  module ReactOnRails
2
5
  class ReactRenderer
6
+ # Reimplement console methods for replaying on the client
7
+ CONSOLE_POLYFILL = <<-JS
8
+ var console = { history: [] };
9
+ ['error', 'log', 'info', 'warn'].forEach(function (level) {
10
+ console[level] = function () {
11
+ console.history.push({level: level, arguments: Array.prototype.slice.call(arguments)});
12
+ };
13
+ });
14
+ JS
3
15
 
4
- # "this" does not need a closure as it refers to the "this" defined by the
5
- # calling the calling context which is the "this" in the execJs environment.
6
- def render_js_react_component
7
- <<-JS.strip_heredoc
8
- function renderReactComponent(componentClass, props) {
9
- return this.React.renderToString(
10
- componentClass(props)
11
- );
12
- }
16
+ # Script to write to the browser console.
17
+ # NOTE: result comes from enclosing closure and is the server generated HTML
18
+ # that we intend to write to the browser. Thus, the script tag will get executed right after
19
+ # the HTML is rendered.
20
+ CONSOLE_REPLAY = <<-JS
21
+ var history = console.history;
22
+ if (history && history.length > 0) {
23
+ result += '\\n<script>';
24
+ history.forEach(function (msg) {
25
+ result += '\\nconsole.' + msg.level + '.apply(console, ' + JSON.stringify(msg.arguments) + ');';
26
+ });
27
+ result += '\\n</script>';
28
+ }
29
+ JS
30
+
31
+ DEBUGGER = <<-JS
32
+ if (typeof window !== 'undefined') { debugger; }
33
+ JS
34
+
35
+ def base_js_code
36
+ <<-JS
37
+ #{CONSOLE_POLYFILL}
38
+ #{bundle_js_code};
13
39
  JS
14
40
  end
15
41
 
16
- def initialize
17
- js_code = "#{bundle_js_code};\n#{render_js_react_component}"
18
- @context = ExecJS.compile(js_code)
42
+ def initialize(options)
43
+ @context = ExecJS.compile(base_js_code)
44
+ @replay_console = options.fetch(:replay_console) { ReactOnRails.configuration.replay_console }
19
45
  end
20
46
 
21
- # Returns a html_safe string of HTML for direct insertion on the page by evaluating a js_code.
22
- # Note, js_code does not have to be based on React.
23
- def render_js(js_code)
24
- js_code_wrapper = <<-JS.strip_heredoc
25
- (function () {
26
- return #{js_code}
27
- })()
47
+ # js_code: JavaScript expression that returns a string.
48
+ # Returns a string of HTML for direct insertion on the page by evaluating js_code.
49
+ # Note, js_code does not have to be based on React.
50
+ # Calling code will probably call 'html_safe' on return value before rendering to the view.
51
+ def render_js(js_code, options = {})
52
+ component_name = options.fetch(:react_component_name, "")
53
+
54
+ result_js_code = "result = #{js_code}"
55
+
56
+ js_code_wrapper = <<-JS
57
+ (function () {
58
+ var result = '';
59
+ #{ReactOnRails::ReactRenderer.wrap_code_with_exception_handler(result_js_code, component_name)}
60
+ #{after_render};
61
+ return result;
62
+ })()
28
63
  JS
29
64
 
30
- # This is the html from the JavaScript. Whatever calls this will probably call 'html_safe'
31
- # on the string.
65
+ trace_rails_on_maui = ENV["TRACE_REACT_ON_RAILS"].present? # Set to anything to print generated code.
66
+ if trace_rails_on_maui
67
+ puts "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
68
+ puts "react_renderer.rb: 92"
69
+ puts "js_code_wrapper = #{js_code_wrapper.ai}"
70
+ puts "wrote file tmp/server-generated.js"
71
+ File.write('tmp/server-generated.js', js_code_wrapper)
72
+ puts "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
73
+ end
74
+
32
75
  @context.eval(js_code_wrapper)
33
76
  end
34
77
 
78
+ def self.wrap_code_with_exception_handler(js_code, component_name)
79
+ <<-JS
80
+ try {
81
+ #{js_code}
82
+ }
83
+ catch(e) {
84
+ var lineOne =
85
+ 'ERROR: You specifed the option generator_function (could be in your defaults) to be\\n';
86
+ var lastLine =
87
+ 'A generator function takes a single arg of props and returns a ReactElement.';
88
+
89
+ var msg = '';
90
+ var shouldBeGeneratorError = lineOne +
91
+ 'false, but the react component \\'#{component_name}\\' seems to be a generator function.\\n' +
92
+ lastLine;
93
+ var reMatchShouldBeGeneratorError = /Can't add property context, object is not extensible/;
94
+ if (reMatchShouldBeGeneratorError.test(e.message)) {
95
+ msg += shouldBeGeneratorError + '\\n\\n';
96
+ console.error(shouldBeGeneratorError);
97
+ }
98
+
99
+ var shouldBeGeneratorError = lineOne +
100
+ 'true, but the react component \\'#{component_name}\\' is not a generator function.\\n' +
101
+ lastLine;
102
+ var reMatchShouldNotBeGeneratorError = /Cannot call a class as a function/;
103
+ if (reMatchShouldNotBeGeneratorError.test(e.message)) {
104
+ msg += shouldBeGeneratorError + '\\n\\n';
105
+ console.error(shouldBeGeneratorError);
106
+ }
107
+
108
+ console.error('SERVER SIDE: Exception in server side rendering!');
109
+ if (e.fileName) {
110
+ console.error('SERVER SIDE: location: ' + e.fileName + ':' + e.lineNumber);
111
+ }
112
+ console.error('SERVER SIDE: message: ' + e.message);
113
+ console.error('SERVER SIDE: stack: ' + e.stack);
114
+ msg += 'SERVER SIDE Exception in rendering!\\n' +
115
+ (e.fileName ? '\\nlocation: ' + e.fileName + ':' + e.lineNumber : '') +
116
+ '\\nMessage: ' + e.message + '\\n\\n' + e.stack;
117
+
118
+ var reactElement = React.createElement('pre', null, msg);
119
+ result = React.renderToString(reactElement);
120
+ }
121
+ JS
122
+ end
123
+
35
124
  private
36
125
 
126
+ def after_render
127
+ @replay_console ? CONSOLE_REPLAY : ""
128
+ end
129
+
37
130
  def bundle_js_code
38
- js_file = Rails.root.join(ReactOnRails.configuration.bundle_js_file)
131
+ js_file = Rails.root.join(ReactOnRails.configuration.server_bundle_js_file)
39
132
  File.read(js_file)
40
133
  end
41
134
  end
@@ -1,3 +1,3 @@
1
1
  module ReactOnRails
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "bundler", "~> 1.10"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
27
  spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "coveralls"
28
29
  end
data/ruby-lint.yml ADDED
@@ -0,0 +1,22 @@
1
+ # Not currently using ruby-lint
2
+ ---
3
+ presenter: syntastic
4
+
5
+ directories:
6
+ - app
7
+ - lib
8
+ - spec
9
+
10
+ ignore_paths:
11
+ - client
12
+ - node_modules
13
+
14
+ analysis_classes:
15
+ # - argument_amount
16
+ - pedantics
17
+ - shadowing_variables
18
+ # Too many false positives for these
19
+ # - undefined_methods
20
+ # - undefined_variables
21
+ # - unused_variables
22
+ - useless_equality_checks
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: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-09-01 00:00:00.000000000 Z
11
+ date: 2015-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: See README.md
84
98
  email:
85
99
  - justin@shakacode.com
@@ -87,20 +101,29 @@ executables: []
87
101
  extensions: []
88
102
  extra_rdoc_files: []
89
103
  files:
104
+ - ".coveralls.yml"
105
+ - ".eslintignore"
106
+ - ".eslintrc"
90
107
  - ".gitignore"
108
+ - ".jscsrc"
91
109
  - ".rspec"
110
+ - ".rubocop.yml"
111
+ - ".scss-lint.yml"
92
112
  - ".travis.yml"
93
113
  - CODE_OF_CONDUCT.md
114
+ - Dockerfile
94
115
  - Gemfile
95
116
  - LICENSE.txt
96
117
  - README.md
97
118
  - Rakefile
98
119
  - app/helpers/react_on_rails_helper.rb
120
+ - docker-compose.yml
99
121
  - lib/react_on_rails.rb
100
122
  - lib/react_on_rails/configuration.rb
101
123
  - lib/react_on_rails/react_renderer.rb
102
124
  - lib/react_on_rails/version.rb
103
125
  - react_on_rails.gemspec
126
+ - ruby-lint.yml
104
127
  homepage: https://github.com/shakacode/react_on_rails
105
128
  licenses:
106
129
  - MIT