react_on_rails 1.0.0.pre → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +2 -0
  3. data/.eslintignore +2 -0
  4. data/.eslintrc +1 -0
  5. data/.gitignore +4 -0
  6. data/.jscsrc +2 -2
  7. data/.rubocop.yml +2 -0
  8. data/.scss-lint.yml +3 -3
  9. data/.travis.yml +31 -18
  10. data/Dockerfile_ci +12 -0
  11. data/Dockerfile_tests +12 -0
  12. data/{LICENSE.txt → LICENSE} +0 -0
  13. data/README.md +170 -290
  14. data/Rakefile +20 -7
  15. data/app/helpers/react_on_rails_helper.rb +5 -5
  16. data/docker-compose.yml +12 -0
  17. data/docs/Contributing.md +26 -2
  18. data/docs/gen-notes/react_syntax.md +3 -0
  19. data/docs/gen-notes/reducers.md +31 -0
  20. data/docs/generator_testing_script.md +50 -0
  21. data/docs/linters.md +8 -0
  22. data/docs/manual_configuration.md +202 -0
  23. data/docs/node_dependencies_and_npm.md +29 -0
  24. data/lib/generators/react_on_rails/base_generator.rb +116 -0
  25. data/lib/generators/react_on_rails/bootstrap_generator.rb +84 -0
  26. data/lib/generators/react_on_rails/generator_helper.rb +48 -0
  27. data/lib/generators/react_on_rails/heroku_deployment_generator.rb +22 -0
  28. data/lib/generators/react_on_rails/install_generator.rb +86 -0
  29. data/lib/generators/react_on_rails/linters_generator.rb +38 -0
  30. data/lib/generators/react_on_rails/react_no_redux_generator.rb +37 -0
  31. data/lib/generators/react_on_rails/react_with_redux_generator.rb +61 -0
  32. data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +4 -0
  33. data/lib/generators/react_on_rails/templates/base/base/REACT_ON_RAILS.md +16 -0
  34. data/lib/generators/react_on_rails/templates/base/base/app/controllers/hello_world_controller.rb +5 -0
  35. data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +6 -0
  36. data/lib/generators/react_on_rails/templates/base/base/client/.babelrc +3 -0
  37. data/lib/generators/react_on_rails/templates/base/base/client/REACT_ON_RAILS_CLIENT_README.md +3 -0
  38. data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/startup/clientGlobals.jsx +4 -0
  39. data/lib/generators/react_on_rails/templates/base/base/client/index.jade +15 -0
  40. data/lib/generators/react_on_rails/templates/base/base/client/npm-shrinkwrap.json +2907 -0
  41. data/lib/generators/react_on_rails/templates/base/base/client/server.js +58 -0
  42. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.base.config.js +58 -0
  43. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.hot.config.js +65 -0
  44. data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.rails.config.js +45 -0
  45. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb +30 -0
  46. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/assets.rake +26 -0
  47. data/lib/generators/react_on_rails/templates/base/base/package.json +31 -0
  48. data/lib/generators/react_on_rails/templates/base/server_rendering/client/app/bundles/HelloWorld/startup/serverGlobals.jsx +3 -0
  49. data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +37 -0
  50. data/lib/generators/react_on_rails/templates/bootstrap/app/assets/stylesheets/_bootstrap-custom.scss +63 -0
  51. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_post-bootstrap.scss +10 -0
  52. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_pre-bootstrap.scss +8 -0
  53. data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_react-on-rails-sass-helper.scss +19 -0
  54. data/lib/generators/react_on_rails/templates/bootstrap/client/bootstrap-sass.config.js +89 -0
  55. data/lib/generators/react_on_rails/templates/client/README.md +97 -0
  56. data/lib/generators/react_on_rails/templates/heroku_deployment/.buildpacks +2 -0
  57. data/lib/generators/react_on_rails/templates/heroku_deployment/Procfile +1 -0
  58. data/lib/generators/react_on_rails/templates/linters/client/.eslintignore +1 -0
  59. data/lib/generators/react_on_rails/templates/linters/client/.eslintrc +17 -0
  60. data/lib/generators/react_on_rails/templates/linters/client/.jscsrc +7 -0
  61. data/lib/generators/react_on_rails/templates/linters/lib/tasks/brakeman.rake +17 -0
  62. data/lib/generators/react_on_rails/templates/linters/lib/tasks/ci.rake +33 -0
  63. data/lib/generators/react_on_rails/templates/linters/lib/tasks/linters.rake +81 -0
  64. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +39 -0
  65. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +33 -0
  66. data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx +11 -0
  67. data/lib/generators/react_on_rails/templates/no_redux/base/client/package.json.tt +75 -0
  68. data/lib/generators/react_on_rails/templates/no_redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +11 -0
  69. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx +8 -0
  70. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +48 -0
  71. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx +8 -0
  72. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +43 -0
  73. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx +21 -0
  74. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/index.jsx +14 -0
  75. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/startup/HelloWorldAppClient.jsx +20 -0
  76. data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/store/helloWorldStore.jsx +35 -0
  77. data/lib/generators/react_on_rails/templates/redux/base/client/app/lib/middlewares/loggerMiddleware.js +25 -0
  78. data/lib/generators/react_on_rails/templates/redux/base/client/package.json.tt +82 -0
  79. data/lib/generators/react_on_rails/templates/redux/server_rendering/client/app/bundles/HelloWorld/startup/HelloWorldAppServer.jsx +21 -0
  80. data/lib/react_on_rails.rb +1 -7
  81. data/lib/react_on_rails/configuration.rb +14 -5
  82. data/lib/react_on_rails/engine.rb +7 -0
  83. data/lib/react_on_rails/server_rendering_pool.rb +14 -1
  84. data/lib/react_on_rails/version.rb +1 -1
  85. data/react_on_rails.gemspec +2 -2
  86. data/ruby-lint.yml +1 -0
  87. metadata +75 -11
  88. data/Dockerfile +0 -14
  89. data/docs/README.md +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b275f388735a62982a5056840c44bf0779da6636
4
- data.tar.gz: 27d0bfbe15a24476c55c9ba6fa8973213e875f1a
3
+ metadata.gz: 5fde8cbadfff66bb7793dbc144644d60d46d4803
4
+ data.tar.gz: 29f6b282949c98382a6821d7b56a987ede72f80c
5
5
  SHA512:
6
- metadata.gz: 168fd64398f5d3e015401652ce81e60fca5a083500cee3bf4645898476fdbc7161f912fe59362e73f633f889f3976de8ff332809a375e9260526b568dd7f4b94
7
- data.tar.gz: bccaeff6f9225a65e246c9eeef5a48d97dcb1e8d96acba82afcd8719690eb095d4d1f8a1a577cf896b4ef540150519adc2fe895e8c0cf71e07f95046b846c795
6
+ metadata.gz: 41b6e18bc73f593867cf322feb405d8c1eb77ccf2063860aac2d519cefc8994708cf838b783fca3b8056cb509bc2e1253d4a7da30874d193271d978d3724b110
7
+ data.tar.gz: 179393aadd9f9d2b1431eb7b21cc436f9e036fe504b25901dd0a69002725032f12daaedaee0e64f3ae05c2d04ef3a412bc05a0ba8b8d72c20aa5f735407eecb8
data/.dockerignore ADDED
@@ -0,0 +1,2 @@
1
+ coverage/
2
+ docker-compose.yml
data/.eslintignore CHANGED
@@ -1 +1,3 @@
1
1
  node_modules
2
+ coverage
3
+ spec/react_on_rails/dummy-for-generators
data/.eslintrc CHANGED
@@ -14,3 +14,4 @@ rules:
14
14
  indent: [1, 2, { SwitchCase: 1, VariableDeclarator: 2 }]
15
15
  react/sort-comp: 0
16
16
  react/jsx-quotes: 0
17
+ id-length: [1, { min: 2, exceptions: [_, e, i, k, v] }]
data/.gitignore CHANGED
@@ -8,11 +8,15 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  *.gem
11
+ /vendor/
11
12
 
12
13
  /spec/dummy/client/node_modules
13
14
  /spec/dummy/app/assets/javascripts/generated/
14
15
  /spec/dummy-react-013/client/node_modules
15
16
  /spec/dummy-react-013/app/assets/javascripts/generated/
17
+ /spec/dummy-react-013/coverage/
18
+ /spec/dummy/coverage/
19
+ /spec/react_on_rails/dummy-for-generators/
16
20
 
17
21
  # RVM
18
22
  .ruby-version
data/.jscsrc CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "preset": "airbnb",
3
3
  "fileExtensions": [".js", ".jsx"],
4
- "excludeFiles": ["**/build/**", "**/node_modules/**", "**/generated/**", "**/docs/**", "**/tmp/**", "**/sample_generated/**"],
5
- "requireTrailingComma": { ignoreSingleValue: true, ignoreSingleLine: true },
4
+ "excludeFiles": ["**/build/**", "**/node_modules/**", "**/generated/**", "**/docs/**", "**/tmp/**", "**/sample_generated/**", "**/coverage/**", "**/vendor/**", "**/dummy-for-generators/**"],
5
+ "requireTrailingComma": { "ignoreSingleValue": true, "ignoreSingleLine": true },
6
6
  "validateQuoteMarks": false
7
7
  }
data/.rubocop.yml CHANGED
@@ -9,12 +9,14 @@ AllCops:
9
9
  - 'vendor/**/*'
10
10
  - 'spec/fixtures/**/*'
11
11
  - 'node_modules/**/*'
12
+ - 'coverage/**/*'
12
13
  - 'db/**/*'
13
14
  - 'db/schema.rb'
14
15
  - 'db/seeds.rb'
15
16
  - 'client/node_modules/**/*'
16
17
  - 'bin/**/*'
17
18
  - !ruby/regexp /old_and_unused\.rb$/
19
+ - 'spec/react_on_rails/dummy-for-generators/**/*'
18
20
 
19
21
  Metrics/LineLength:
20
22
  Max: 120
data/.scss-lint.yml CHANGED
@@ -1,9 +1,9 @@
1
1
  # See http://sass-guidelin.es/#zeros
2
2
 
3
3
  scss_files:
4
- - 'app/assets/stylesheets/**/*.scss'
5
- - 'client/assets/stylesheets/**/*.scss'
6
-
4
+ - 'spec/dummy/app/assets/stylesheets/**/*.scss'
5
+ exclude:
6
+ - 'spec/dummy/app/assets/stylesheets/application.css'
7
7
  linters:
8
8
  # BangFormat:
9
9
  # enabled: true
data/.travis.yml CHANGED
@@ -1,33 +1,46 @@
1
+ sudo: required
2
+
1
3
  language: ruby
4
+
2
5
  rvm:
3
- - 2.2.2
6
+ - 2.2.3
7
+
8
+ services:
9
+ - docker
4
10
 
5
11
  gemfile:
6
- - spec/dummy/Gemfile
12
+ - spec/dummy/Gemfile
7
13
 
8
14
  env:
9
- - export RAILS_ENV=test
15
+ - export RAILS_ENV=test
16
+
17
+ before_install:
18
+ - sudo apt-get update
19
+ - curl -L https://github.com/docker/compose/releases/download/1.4.0/docker-compose-`uname -s`-`uname -m` > docker-compose
20
+ - chmod +x docker-compose
21
+ - sudo mv docker-compose /usr/local/bin
22
+ - sudo apt-get install -y xvfb
10
23
 
11
24
  install:
12
- - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install 4.2.0
13
- - npm install -g npm
14
- - bundle install
15
- - cd spec/dummy/client && npm install
16
- - $(npm bin)/webpack --config webpack.server.js
17
- - $(npm bin)/webpack --config webpack.client.js
18
- - cd ../../dummy-react-013/client && npm install
19
- - $(npm bin)/webpack --config webpack.server.js
20
- - $(npm bin)/webpack --config webpack.client.js
25
+ - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install 4.2.0
26
+ - npm install -g npm
27
+ - bundle install
28
+ - cd spec/dummy/client && npm install
29
+ - $(npm bin)/webpack --config webpack.server.js
30
+ - $(npm bin)/webpack --config webpack.client.js
31
+ - cd ../../dummy-react-013/client && npm install
32
+ - $(npm bin)/webpack --config webpack.server.js
33
+ - $(npm bin)/webpack --config webpack.client.js
34
+ - cd ../../../
35
+ - docker-compose up lint
21
36
 
22
37
  before_script:
23
- - cd ../../
24
- - export DISPLAY=:99.0
25
- - sh -e /etc/init.d/xvfb start
38
+ - "export DISPLAY=:99"
39
+ - Xvfb :99 -ac -screen scn 1600x1200x16 &
26
40
 
27
41
  script:
28
- - rake run_rspec:gem
29
- - DRIVER=selenium_firefox rake run_rspec:dummy
30
- - DRIVER=selenium_firefox rake run_rspec:dummy_react_013
42
+ - rake
43
+ - rake docker:lint
31
44
 
32
45
  notifications:
33
46
  slack:
data/Dockerfile_ci ADDED
@@ -0,0 +1,12 @@
1
+ FROM dylangrafmyre/docker-ci
2
+
3
+ WORKDIR /app/
4
+
5
+ COPY ["/lib/react_on_rails/version.rb", "/app/lib/react_on_rails/"]
6
+ COPY ["Gemfile", "Gemfile.lock", "react_on_rails.gemspec", "/app/"]
7
+ COPY ["/spec/dummy/Gemfile", "/spec/dummy/Gemfile.lock", "/app/spec/dummy/"]
8
+ RUN bundle install --gemfile=spec/dummy/Gemfile
9
+
10
+ ENV DISPLAY :99
11
+ ENTRYPOINT service xvfd start \
12
+ && rake ci
data/Dockerfile_tests ADDED
@@ -0,0 +1,12 @@
1
+ FROM dylangrafmyre/docker-ci
2
+
3
+ WORKDIR /app/
4
+
5
+ COPY ["/lib/react_on_rails/version.rb", "/app/lib/react_on_rails/"]
6
+ COPY ["Gemfile", "Gemfile.lock", "react_on_rails.gemspec", "/app/"]
7
+ COPY ["/spec/dummy/Gemfile", "/spec/dummy/Gemfile.lock", "/app/spec/dummy/"]
8
+ RUN bundle install --gemfile=spec/dummy/Gemfile
9
+
10
+ ENV DISPLAY :99
11
+ ENTRYPOINT service xvfd start \
12
+ && rake
File without changes
data/README.md CHANGED
@@ -1,341 +1,221 @@
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)
4
- # React On Rails
5
-
6
- Gem Published: https://rubygems.org/gems/react_on_rails
7
-
8
- Live example, including server rendering + redux: http://www.reactrails.com/
9
- Sponsored by [ShakaCode.com](http://www.shakacode.com/)
10
-
11
- See [Action Plan for v1.0](https://github.com/shakacode/react_on_rails/issues/1). We're ready v1.0.
12
-
13
- Feedback and pull-requests encouraged! Thanks in advance! We've got a private slack channel to discuss react + webpack + rails. [Email us for an invite contact@shakacode.com](mailto: contact@shakacode.com).
14
-
15
- Supports:
16
-
17
- 1. Rails
18
- 2. Webpack
19
- 3. React, both v0.14 and v0.13.
20
- 4. Redux
21
- 5. Turbolinks
22
- 6. Server side rendering with fragment caching
23
- 7. react-router for client side rendering (and server side very soon)
24
-
25
- ## OPEN ISSUES
26
- 1. Almost all the open issues are nice to haves like more tests.
27
- 2. If you want to work on any of the open issues, please comment on the issue. My team is mentoring anybody that's trying to help with the issues.
28
- 3. Longer term, we hope to put in many conveniences into this gem, in terms of Webpack + Rails integration. We're open to suggestions.
29
-
30
- ## Links
31
- 1. See https://github.com/shakacode/react-webpack-rails-tutorial/ for how to integrate it!
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.shakacode.com
34
- 4. If you're looking for consulting on a project using React and Rails, [email us! contact@shakacode.com](mailto: contact@shakacode.com)? You can first join our slack room for some free advice.
35
- 5. We're looking for great developers that want to work with Rails + React with a distributed, worldwide team, for our own
36
- products, client work, and open source. [More info here](http://www.shakacode.com/about/index.html#work-with-us).
37
-
38
- ## How is different than the [react-rails gem](https://github.com/reactjs/react-rails)?
39
- 1. `react_on_rails` depends on [webpack](http://webpack.github.io/). `react-rails` integrates closely with sprockets and
40
- helps you integrate JSX and the react code into a Rails project.
41
- 2. Likewise, using Webpack as shown in the [react-webpack-rails-tutorial](https://github.com/justin808/react-webpack-rails-tutorial/)
42
- does involve some extra setup. However, we feel that tight and simple integration with the node ecosystem is more than
43
- worth any minor setup costs.
44
- 3. `react-rails` depends on `jquery-ujs` for client side rendering. `react_on_rails` has it's own JS code that does not
45
- depend on jquery.
46
-
47
- ## Installation Checklist
48
- 1. Include the gems `react_on_rails` and `therubyracer` like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/361f4338ebb39a5d3934b00cb6d6fcf494773000/Gemfile#L42) and run `bundle`. Note, you can sustitute your preferable JavaScript engine.
1
+ [![Build Status](https://travis-ci.org/shakacode/react_on_rails.svg?branch=master)](https://travis-ci.org/shakacode/react_on_rails) [![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) [![Dependency Status](https://gemnasium.com/shakacode/react_on_rails.svg)](https://gemnasium.com/shakacode/react_on_rails) [![Gem Version](https://badge.fury.io/rb/react_on_rails.svg)](https://badge.fury.io/rb/react_on_rails)
2
+
3
+ # React on Rails
4
+ React on Rails integrates Facebook's [React](https://github.com/facebook/react) front-end framework with Rails. Currently, both React v0.14 and v0.13 are supported. See the Rails on Maui [blog post](http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/) that started it all!
5
+
6
+ Like the [react-rails](https://github.com/reactjs/react-rails) gem, React on Rails is capable of server-side rendering with fragment caching and is compatible with [turbolinks](https://github.com/rails/turbolinks). Unlike react-rails, which depends heavily on sprockets and jquery-ujs, React on Rails uses [webpack](http://webpack.github.io/) and does not depend on jQuery. While the initial setup is slightly more involved, it allows for advanced functionality such as:
7
+
8
+ + [Redux](https://github.com/rackt/redux)
9
+ + [Webpack dev server](https://webpack.github.io/docs/webpack-dev-server.html) with [hot module replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html)
10
+ + [Webpack optimization functionality](https://github.com/webpack/docs/wiki/optimization)
11
+ + **(Coming Soon)** [React Router](https://github.com/rackt/react-router)
12
+
13
+ See the [react-webpack-rails-tutorial](https://github.com/justin808/react-webpack-rails-tutorial/) for an example of a live implementation and code.
14
+
15
+ ### Including your React Component in your Rails Views
16
+ Please see [Getting Started](#getting-started) for how to set up your Rails project for React on Rails if you have not already done so.
17
+
18
+ + *Normal Mode (JavaScript is rendered on client):*
19
+
20
+ ```erb
21
+ <%= react_component("HelloWorldApp", @some_props) %>
22
+ ```
23
+ + *Server-Side Rendering:*
24
+
25
+ ```erb
26
+ <%= react_component("HelloWorldApp", @some_props, prerender: true) %>
27
+ ```
28
+
29
+ + The `component_name` parameter here would be a string matching the name you used when globally exposing your React component.
30
+ + `@some_props` can be either a hash or JSON string or {} if you have no props. This will make the data available in your component:
31
+
32
+ ```javascript
33
+ this.props.name
34
+ ```
35
+
36
+ ### Client-Side Rendering vs. Server-Side Rendering
37
+ In most cases, you should use the provided helper method to render the React component from your Rails views with `prerender: false` (default behavior). In some cases, such as when SEO is vital or many users will not have JavaScript enabled, you can pass the `--server-rendering` option to the generator to configure your application for server-side rendering. Your JavaScript can then be first rendered on the server and passed to the client as HTML.
38
+
39
+ In the following screenshot you can see the actual HTML rendered for a side-by-side comparison of a React component left as JavaScript for the client to render followed by the same component rendered on the server to HTML along with any console error messages generated:
40
+
41
+ ![Comparison of a normal React Component with its server-rendered version](https://cloud.githubusercontent.com/assets/1118459/10157268/41435186-6624-11e5-9341-6fc4cf35ee90.png)
42
+
43
+ ## Getting Started
44
+ 1. Add the following to your Gemfile and bundle install:
49
45
 
50
46
  ```ruby
51
47
  gem "react_on_rails"
52
48
  gem "therubyracer"
53
49
  ```
54
- 1. Globally expose React in your webpack config like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.client.base.config.js#L31):
55
-
56
- ```javascript
57
- module: {
58
- loaders: [
59
- // React is necessary for the client rendering:
60
- {test: require.resolve('react'), loader: 'expose?React'},
61
- ```
62
- 1. Require `react_on_rails` in your `application.js` like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/361f4338ebb39a5d3934b00cb6d6fcf494773000/app/assets/javascripts/application.js#L15). It possibly should come after you require `turbolinks`:
63
-
64
- ```
65
- //= require react_on_rails
50
+
51
+ 2. Run the generator with a simple "Hello World" example:
52
+
53
+ ```bash
54
+ rails generate react_on_rails:install
66
55
  ```
67
- 1. Expose your client globals like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/app/startup/clientGlobals.jsx#L3):
68
-
69
- ```javascript
70
- import App from './ClientApp';
71
- window.App = App;
72
- ```
73
- 1. Put your client globals file as webpack entry points like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.client.rails.config.js#L22). Similar pattern for server rendering.
74
-
75
- ```javascript
76
- config.entry.app.push('./app/startup/clientGlobals');
56
+
57
+ 3. NPM install:
58
+
59
+ ```bash
60
+ npm install
77
61
  ```
78
- 1. See customization of configuration options below.
79
62
 
80
- ### Additional Steps For Server Rendering (option `prerender` shown below)
81
- See the next section for a sample webpack.server.rails.config.js.
82
- 1. Expose your server globals like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/app/startup/serverGlobals.jsx#L7)
83
-
84
- ```javascript
85
- import App from './ServerApp';
86
- global.App = App;
87
- ```
88
- 2. Make the server globals file an entry point in your webpack config, like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.server.rails.config.js#L7)
89
-
90
- ```javascript
91
- entry: ['./app/startup/serverGlobals'],
92
- ```
93
- 3. Ensure the name of your ouput file (shown [here](https://github.com/shakacode/react-webpack-rails-tutorial/blob/537c985dc82faee333d80509343ca32a3965f9dd/client/webpack.server.rails.config.js#L9)) of your server bundle corresponds to the configuration of the gem. The default path is `app/assets/javascripts/generated`. See below for customization of configuration variables.
94
- 4. Expose `React` in your webpack config, like [this](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/webpack.server.rails.config.js#L23)
95
-
96
- #### Sample webpack.server.rails.config.js (ONLY for server rendering)
97
- Be sure to check out the latest example version of [client/webpack.server.rails.config.js](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/webpack.server.rails.config.js).
98
-
99
- ```javascript
100
- // Common webpack configuration for server bundle
101
-
102
- module.exports = {
103
-
104
- // the project dir
105
- context: __dirname,
106
- entry: ['./app/startup/serverGlobals'],
107
- output: {
108
- filename: 'server-bundle.js',
109
- path: '../app/assets/javascripts/generated',
110
-
111
- // CRITICAL to set libraryTarget: 'this' for enabling Rails to find the exposed modules IF you
112
- // use the "expose" webpackfunctionality. See startup/serverGlobals.jsx.
113
- // NOTE: This is NOT necessary if you use the syntax of global.MyComponent = MyComponent syntax.
114
- // See http://webpack.github.io/docs/configuration.html#externals for documentation of this option
115
- //libraryTarget: 'this',
116
- },
117
- resolve: {
118
- extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx', 'config.js'],
119
- },
120
- module: {
121
- loaders: [
122
- {test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/},
123
-
124
- // React is necessary for the client rendering:
125
- { test: require.resolve('react'), loader: 'expose?React' },
126
- { test: require.resolve('react-dom/server'), loader: 'expose?ReactDOMServer' },
127
- ],
128
- },
129
- };
130
- ```
63
+ 4. Start your Rails server:
131
64
 
132
- ## What Happens?
65
+ ```bash
66
+ foreman start -f Procfile.dev
67
+ ```
133
68
 
134
- Here's what the browser will render with a call to the `react_component` helper.
135
- ![2015-09-28_20-24-35](https://cloud.githubusercontent.com/assets/1118459/10157268/41435186-6624-11e5-9341-6fc4cf35ee90.png)
69
+ 5. Visit [localhost:3000/hello_world](http://localhost:3000/hello_world)
136
70
 
137
- ## Usage
71
+ ## How it Works
72
+ The generator installs your webpack files in the `client` folder. Foreman uses webpack to compile your code and output the bundled results to `app/assets/javascripts/generated`, which are then loaded by sprockets. These generated bundle files have been added to your `.gitignore` for your convenience.
138
73
 
139
- *See section below titled "Try it out"*
74
+ Inside your Rails views, you can now use the `react_component` helper method provided by React on Rails.
140
75
 
141
- ### Helper Method
142
- The main API is a helper:
76
+ ### Building the Bundles
77
+ Each time you change your client code, you will need to re-generate the bundles. The included Foreman `Procfile.dev` will take care of this for you by watching your JavaScript code files for changes. Simply run `foreman start -f Procfile.dev`.
143
78
 
144
- ```ruby
145
- <%= react_component(component_name, props = {}, options = {}) %>
146
- ```
147
-
148
- Params are:
79
+ ### Globally Exposing Your React Components
80
+ Place your JavaScript code inside of the provided `client/app` folder. Use modules just as you would when using webpack alone. The difference here is that instead of mounting React components directly to an element using `React.render`, you **expose your components globally and then mount them with helpers inside of your Rails views**.
81
+
82
+ + *Normal Mode (JavaScript is Rendered on client):*
149
83
 
150
- * **react_component_name**: [string] can be a React component, created using a ES6 class, or React.createClass,
151
- or a `generator function` that returns a React component
152
-
153
- using ES6
154
84
  ```javascript
155
- let MyReactComponentApp = (props) => <MyReactComponent {...props}/>;
156
- ```
157
-
158
- or using ES5
85
+ window.HelloWorld = HelloWorldAppClient;
86
+ ```
87
+ + *Server-Side Rendering:*
88
+
159
89
  ```javascript
160
- var MyReactComponentApp = function(props) { return <YourReactComponent {...props}/>; }
90
+ global.HelloWorld = HelloWorldAppServer;
161
91
  ```
162
- Exposing the react_component_name is necessary to both a plain ReactComponent as well as
163
- a generator:
164
- For client rendering, expose the react_component_name on window:
165
92
 
166
- ```javascript
167
- window.MyReactComponentApp = MyReactComponentApp;
168
- ```
169
- For server rendering, export the react_component_name on global:
170
- ```javascript
171
- global.MyReactComponentApp = MyReactComponentApp;
172
- ```
173
- If you're curious as to what the gem generates for the server and client rendering, see [`spec/dummy/client/app/startup/serverGlobals.jsx`](https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/spec/sample_generated_js/server-generated.js)
174
- and [`spec/dummy/client/app/startup/ClientReduxApp.jsx`](https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/spec/sample_generated_js/client-generated.js) for examples of this. Note, this is not the code that you are providing. You can see the client code by viewing the page source.
175
-
176
- * **props**: [hash | string of json] Properties to pass to the react object. See this example if you're using Jbuilder: [react-webpack-rails-tutorial view rendering props using jBuilder](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/app/views/pages/index.html.erb#L20)
177
93
 
178
- ```erb
179
- <%= react_component('App', render(template: "/comments/index.json.jbuilder"),
180
- generator_function: true, prerender: true) %>
94
+ ## Generator Options
95
+ Run `rails generate react_on_rails:install --help` for descriptions of all available options:
96
+
181
97
  ```
182
- * **options:** [hash]
183
- * **generator_function**: <true/false> default is false, set to true if you want to use a generator function rather than a React Component.
184
- * **prerender**: <true/false> set to false when debugging!
185
- * **trace**: <true/false> set to true to print additional debugging information in the browser default is true for development, off otherwise
186
- * **replay_console**: <true/false> Default is true. False will disable echoing server rendering logs, which can make troubleshooting server rendering difficult.
187
- * Any other options are passed to the content tag, including the id.
188
-
189
- ## JavaScript
190
-
191
- 1. Configure your webpack configuration to create the file used for server rendering if you plan to
192
- do server rendering.
193
- 2. Follow the examples in `spec/dummy/client/app/startup/clientGlobals.jsx` to expose your react components
194
- for client side rendering.
195
- ```ruby
196
- import HelloWorld from '../components/HelloWorld';
197
- window.HelloWorld = HelloWorld;
198
- ```
199
- 3. Follow the examples in `spec/dummy/client/app/startup/serverGlobals.jsx` to expose your react components
200
- for server side rendering.
201
- ```ruby
202
- import HelloWorld from '../components/HelloWorld';
203
- global.HelloWorld = HelloWorld;
204
- ```
205
-
206
- ## Server Rendering Tips
207
-
208
- - Your code can't reference `document`. Server side JS execution does not have access to `document`, so jQuery and some
209
- other libs won't work in this environment. You can debug this by putting in `console.log`
210
- statements in your code.
211
- - You can conditionally avoid running code that references document by passing in a boolean prop to your top level react
212
- component. Since the passed in props Hash from the view helper applies to client and server side code, the best way to
213
- do this is to use a generator function.
214
-
215
- You might do something like this in some file for your top level component:
216
- ```javascript
217
- global.App = () => <MyComponent serverSide={true} />;
98
+ Usage:
99
+ rails generate react_on_rails:install [options]
100
+
101
+ Options:
102
+ -R, [--redux], [--no-redux] # Setup Redux files
103
+ -S, [--server-rendering], [--no-server-rendering] # Configure for server-side rendering of webpack JavaScript
104
+ -L, [--skip-linters], [--no-skip-linters] # Don't install linter files
105
+
106
+ Runtime options:
107
+ -f, [--force] # Overwrite files that already exist
108
+ -p, [--pretend], [--no-pretend] # Run but do not make any changes
109
+ -q, [--quiet], [--no-quiet] # Suppress status output
110
+ -s, [--skip], [--no-skip] # Skip files that already exist
111
+
112
+ Description:
113
+ Create react on rails files for install generator.
218
114
  ```
219
115
 
220
- The point is that you have separate files for top level client or server side, and you pass some extra option indicating that rendering is happening server sie.
116
+ We have a repo showing the results of running the generator with various combinations of options, each combination on its own branch: [Generator Results](https://github.com/shakacode/react_on_rails-generator-results-pre-0/pulls).
221
117
 
222
- ## Optional Configuration
118
+ ### Understanding the Organization of the Generated Client Code
119
+ The generated client code follows our organization scheme. Each unique set of functionality, is given its own folder inside of `client/app/bundles`. This encourages for modularity of DOMAINS.
223
120
 
224
- Create a file `config/react_on_rails.rb` to override any defaults. If you don't specify this file,
225
- the default options are below.
121
+ Inside of the generated "HelloWorld" domain you will find the following folders:
226
122
 
227
- The `server_bundle_js_file` must correspond to the bundle you want to use for server rendering.
123
+ + `startup`: two types of files, one that return a container component and implement any code that differs between client and server code (if using server-rendering), and a `clientGlobals` file that exposes the aforementioned files (as well as a `serverGlobals` file if using server rendering). These globals files are what webpack is using as an entry point.
124
+ + `containers`: "smart components" (components that have functionality and logic that is passed to child "dumb components").
125
+ + `components`: includes "dumb components", or components that simply render their properties and call functions given to them as properties by a parent component. Ultimately, at least one of these dumb components will have a parent container component.
228
126
 
229
- ```ruby
230
- # Shown below are the defaults for configuration
231
- ReactOnRails.configure do |config|
232
- # Client bundles are configured in application.js
233
- # Server bundle is a single file for all server rendering of components.
234
- config.server_bundle_js_file = "app/assets/javascripts/generated/server.js" # This is the default
127
+ You may also notice the `app/lib` folder. This is for any code that is common between bundles and therefore needs to be shared (for example, middleware).
235
128
 
236
- # Below options can be overriden by passing to the helper method.
237
- config.prerender = false # default is false
238
- config.generator_function = false # default is false, meaning that you expose ReactComponents directly
239
- config.trace = Rails.env.development? # default is true for development, off otherwise
129
+ #### Additional Redux Folders
130
+ If you have used the `--redux` generator option, you will notice the familiar additional redux folders in addition to the aforementioned folders. In this organization paradigm, each bundle has its own store. We do not set a global store and then use partial stores based off of that. Again, this is for bundle code modularity and isolation. Note that if you want to reuse redux reducers across domains, then you will want to put the shared reducers under `/client/app/lib`.
240
131
 
241
- # For server rendering. This can be set to false so that server side messages are discarded.
242
- config.replay_console = true # Default is true. Be cautious about turning this off.
243
- config.logging_on_server = true # Default is true. Logs server rendering messags to Rails.logger.info
244
-
245
- # Settings for the pool of renderers:
246
- config.server_renderer_pool_size ||= 1 # ExecJS doesn't allow more than one on MRI
247
- config.server_renderer_timeout ||= 20 # seconds
248
- end
249
- ```
132
+ ### Using Images and Fonts
133
+ The generator has amended the folders created in `client/assets/` to Rails's asset path. We would that if you have any existing assets that you want to use with your client code that you should move them to these folders and use webpack as normal.
134
+
135
+ Alternatively, if you have many existing assets and don't wish to move them, you could consider creating symlinks from client/assets that point to your Rails assets folders inside of `app/assets/`. The assets there will then be visible to both Rails and webpack.
136
+
137
+ ### Bootstrap Integration
138
+ React on Rails ships with Twitter Bootstrap already integrated into the build. Note that the generator removes `require_tree` in both the application.js and application.css.scss files. This is to ensure the correct load order for the bootstrap integration, and is usually a good idea in general. You will therefore need to explicitly require your files.
139
+
140
+ How the Bootstrap library is loaded depends upon whether one is using the Rails server or the HMR development server.
141
+
142
+ #### Bootstrap via Rails Server
143
+ In the former case, the Rails server loads `bootstrap-sprockets`, provided by the `bootstrap-sass` ruby gem (added automatically to your Gemfile by the generator) via the `app/assets/stylesheets/_bootstrap-custom.scss` partial.
250
144
 
251
- You can configure your pool of JS virtual machines and specify where it should load code:
145
+ This allows for using Bootstrap in your regular Rails stylesheets. If you wish to customize any of the Bootstrap variables, you can do so via the `client/assets/stylesheets/_pre-bootstrap.scss` partial.
252
146
 
253
- - On MRI, use `therubyracer` for the best performance (see [discussion](https://github.com/reactjs/react-rails/pull/290))
254
- - On MRI, you'll get a deadlock with `pool_size` > 1
255
- - If you're using JRuby, you can increase `pool_size` to have real multi-threaded rendering.
147
+ #### Bootstrap via Webpack HMR Dev Server
148
+ When using the webpack dev server, which does not go through Rails, bootstrap is loaded via the [bootstrap-sass-loader](https://github.com/shakacode/bootstrap-sass-loader) which uses the `client/bootstrap-sass-config.js` file.
256
149
 
257
- # Try it out in the simple sample app
258
- Contributions and pull requests welcome!
150
+ #### Keeping Custom Bootstrap Configurations Synced
151
+ Because the HMR dev server and Rails each load Bootstrap via a different file (explained in the two sections immediately above), any changes to the way components are loaded in one file must also be made to the other file in order to keep styling consistent between the two. For example, if an import is excluded in `_bootstrap-custom.scss`, the same import should be excluded in `bootstrap-sass-config.js` so that styling in the Rails server and the webpack dev server will be the same.
152
+
153
+ ## Rails View Helpers In-Depth
154
+ 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.
155
+
156
+ This is how you actually render the React components you exposed to `window` inside of `clientGlobals` (and `global` inside of `serverGlobals` if you are server rendering).
157
+
158
+ `react_component(component_name, props = {}, options = {})`
159
+ + **react_component_name:** Can be a React component, created using a ES6 class, or `React.createClass`, or a generator function that returns a React component.
160
+ + **props:** Ruby Hash which contains the properties to pass to the react object
161
+ + **options:**
162
+ + **generator_function:** default is false, set to true if you want to use a generator function rather than a React Component.
163
+ + **prerender:** enable server-side rendering of component. Set to false when debugging!
164
+ + **trace:** set to true to print additional debugging information in the browser. Defaults to true for development, off otherwise.
165
+ + **replay_console:** Default is true. False will disable echoing server-rendering logs to the browser. While this can make troubleshooting server rendering difficult, so long as you have the default configuration of logging_on_server set to true, you'll still see the errors on the server.
166
+ + Any other options are passed to the content tag, including the id
167
+
168
+ `def server_render_js(js_expression, options = {})`
169
+
170
+ 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.
171
+
172
+ ## Developing with Webpack Dev Server
173
+ One of the benefits of using webpack is access to [webpack's dev server](https://webpack.github.io/docs/webpack-dev-server.html) and its [hot module replacement](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html) functionality.
174
+
175
+ The webpack dev server with HMR will apply changes from the code (or styles!) to the browser as soon as you save whatever file you're working on. You won't need to reload the page, and your data will still be there. Start foreman as normal (it boots up the Rails server *and* the webpack HMR dev server at the same time).
259
176
 
260
- 1. Setup and run the test app in `spec/dummy`. Note, there's no database.
261
177
  ```bash
262
- cd spec/dummy
263
- bundle
264
- npm i
265
- foreman start
178
+ foreman start -f Procfile.dev
266
179
  ```
267
- 3. Visit http://localhost:3000
268
- 4. Notice that the first time you hit the page, you'll see a message that server is rendering.
269
- See `spec/dummy/app/views/pages/index.html.erb:17` for the generation of that message.
270
- 5. Look at the layouts in `spec/dummy/app/views/pages` for samples of usage.
271
- 5. Open up the browser console and see some tracing.
272
- 6. Open up the source for the page and see the server rendered code.
273
- 7. If you want to turn on server caching for development, run the server like:
274
- `export RAILS_USE_CACHE=YES && foreman start`
275
- 2. If you're testing with caching, you'll need to open the console and run `Rails.cache.clear` to clear
276
- the cache. Note, even if you stop the server, you'll still have the cache entries around.
277
- 8. If you click back and forth between the react page links, you can see the rails console
278
- log as well as the browser console to see what's going on with regards to server rendering and
279
- caching.
280
-
281
- # Key Tips
282
- 1. See sample app in `spec/dummy` for how to set this up. See note below on ensuring you
283
- **DO NOT RUN `rails s` and instead run `foreman start`.
284
- 2. Test out the different options and study the JSX samples in `spec/dummy/client/app/startup`.
285
- 3. Experiment with changing the settings on the `render_component` helper calls in the ERB files.
286
- 2. The file used for server rendering is hard coded as `generated/server.js`
287
- (assets/javascripts/generated/server.js).
288
- 3. The default for rendering right now is `prerender: false`. **NOTE:** Server side rendering does
289
- not work for some components, namely react-router, that use an async setup for server rendering.
290
- You can configure the default for prerender in your config.
291
- 4. You can expose either a React component or a function that returns a React component. If you
292
- wish to create a React component via a function, rather than simply props, then you need to set
293
- the property "generator" on that function to true. When that is done, the function is invoked
294
- with a single parameter of "props", and that function should return a React element.
295
- 5. Be sure you can first render your react component client only before you try to debug server
296
- rendering!
297
- 4. Open up the HTML source and take a look at the generated HTML and the JavaScript to see what's
298
- going on under the covers. Not that when server rendering is turned on, then you'll see the
299
- server rendered react components. When server rendering is turned off, then you'll only see
300
- the `div` element where the inline JavaScript will render the component. You might also notice
301
- how the props you pass (a Ruby Hash) becomes inline JavaScript on the HTML page.
302
-
303
- ## JavaScript Runtime Configuration
304
- See this [discussion on JavaScript performance](https://github.com/shakacode/react_on_rails/issues/21).
305
- The net result is that you want to add this line to your Gemfile to get therubyracer as your default
306
- JavaScript engine.
307
-
308
- ```ruby
309
- gem "therubyracer"
310
- ```
311
180
 
312
- ## References
313
- * [Making the helper for server side rendering work with JS created by Webpack] (https://github.com/reactjs/react-rails/issues/301#issuecomment-133098974)
314
- * [Add Demonstration of Server Side Rendering](https://github.com/justin808/react-webpack-rails-tutorial/issues/2)
315
- * [Charlie Marsh's article "Rendering React Components on the Server"](http://www.crmarsh.com/react-ssr/)
316
- * [Node globals](https://nodejs.org/api/globals.html#globals_global)
181
+ Open your browser to [localhost:4000](http://localhost:4000). Whenever you make changes to your JavaScript code in the `client` folder, they will automatically show up in the browser. Hot module replacement is already enabled by default.
317
182
 
318
- ### Generated JavaScript
183
+ Note that **React-related error messages are typically significantly more helpful when encountered in the dev server** than the Rails server as they do not include noise added by the React on Rails gem.
319
184
 
320
- 1. See spec/dummy/spec/sample_generated_js/server-generated.js to see the JavaScript for typical server rendering.
321
- 2. See spec/dummy/spec/sample_generated_js/client-generated.js to see the JavaScript for typical client rendering.
185
+ ### Adding Additional Routes for the Dev Server
186
+ As you add more routes to your front-end application, you will need to make the corresponding API for the dev server in `client/server.js`. See our example `server.js` from our [tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/client/server.js).
322
187
 
323
- ## Contributing
188
+ ## Additional Documentation:
324
189
 
325
- 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.
190
+ + [Linters](docs/linters.md)
191
+ + [Manual Configuration](docs/manual_configuration.md)
192
+ + [Node Dependencies and NPM](docs/node_dependencies_and_npm.md)
326
193
 
327
- More [tips on contributing here](docs/Contributing.md)
328
-
329
- ## License
194
+ ## Contributing
195
+ Bug reports and pull requests are welcome. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to our version of the [Contributor Covenant](contributor-covenant.org) code of conduct (see [CODE OF CONDUCT](CODE_OF_CONDUCT.md)).
330
196
 
331
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
197
+ See [Contributing](docs/Contributing.md) to get started.
332
198
 
333
- # Authors
199
+ ## License
200
+ The gem is available as open source under the terms of the [MIT License](LICENSE).
334
201
 
202
+ ## Authors
335
203
  [The Shaka Code team!](http://www.shakacode.com/about/)
336
204
 
337
205
  1. [Justin Gordon](https://github.com/justin808/)
338
206
  2. [Samnang Chhun](https://github.com/samnang)
339
207
  3. [Alex Fedoseev](https://github.com/alexfedoseev)
208
+ 4. [Rob Wise](https://github.com/robwise)
209
+ 5. [Blaine Hatab](https://github.com/jbhatab)
210
+ 6. [Roger Studner](https://github.com/rstudner)
211
+ 7. [Aaron Van Bokhoven](https://github.com/aaronvb)
340
212
 
341
213
  And based on the work of the [react-rails gem](https://github.com/reactjs/react-rails)
214
+
215
+ ## About [ShakaCode](http://www.shakacode.com/)
216
+
217
+ Visit [our forums!](http://forum.shakacode.com)
218
+
219
+ If you're looking for consulting on a project using React and Rails, email us ([contact@shakacode.com](mailto: contact@shakacode.com))! You can also join our slack room for some free advice.
220
+
221
+ We're looking for great developers that want to work with Rails + React with a distributed, worldwide team, for our own products, client work, and open source. [More info here](http://www.shakacode.com/about/index.html#work-with-us).