react_on_rails 2.0.0.rc.1 → 2.0.0.rc.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintrc +1 -1
- data/.rubocop.yml +1 -1
- data/.travis.yml +1 -2
- data/CHANGELOG.md +46 -0
- data/Gemfile +0 -7
- data/README.md +16 -2
- data/Rakefile +1 -1
- data/docs/additional_reading/manual_installation.md +3 -4
- data/lib/generators/react_on_rails/base_generator.rb +12 -6
- data/lib/generators/react_on_rails/bootstrap_generator.rb +5 -4
- data/lib/generators/react_on_rails/dev_tests_generator.rb +20 -2
- data/lib/generators/react_on_rails/generator_helper.rb +8 -5
- data/lib/generators/react_on_rails/generator_messages.rb +39 -0
- data/lib/generators/react_on_rails/heroku_deployment_generator.rb +3 -3
- data/lib/generators/react_on_rails/install_generator.rb +34 -14
- data/lib/generators/react_on_rails/js_linters_generator.rb +1 -1
- data/lib/generators/react_on_rails/react_no_redux_generator.rb +5 -7
- data/lib/generators/react_on_rails/react_with_redux_generator.rb +1 -2
- data/lib/generators/react_on_rails/ruby_linters_generator.rb +5 -3
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-hot.tt +4 -0
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +0 -1
- data/lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx.tt +66 -0
- data/lib/generators/react_on_rails/templates/base/base/client/package.json.tt +3 -2
- data/lib/generators/react_on_rails/templates/base/base/client/server.js +2 -2
- data/lib/generators/react_on_rails/templates/base/base/client/{webpack.client.base.config.js.tt → webpack.client.base.config.js} +4 -2
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.hot.config.js.tt +6 -6
- data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.rails.config.js +3 -3
- data/lib/generators/react_on_rails/templates/base/base/package.json +4 -1
- data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +3 -3
- data/lib/generators/react_on_rails/templates/bootstrap/client/assets/stylesheets/_post-bootstrap.scss +1 -1
- data/lib/generators/react_on_rails/templates/js_linters/client/.eslintrc +1 -1
- data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +9 -7
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/containers/HelloWorld.jsx +6 -1
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx +4 -4
- data/lib/generators/react_on_rails/templates/ruby_linters/{ruby-lint.yml → ruby-lint.yml.tt} +6 -0
- data/lib/react_on_rails/version.rb +1 -1
- data/package.json +5 -3
- data/rakelib/example_type.rb +1 -1
- data/rakelib/lint.rake +4 -3
- data/react_on_rails.gemspec +12 -2
- data/ruby-lint.yml +1 -0
- metadata +153 -12
- data/lib/generators/react_on_rails/templates/no_redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +0 -39
- data/lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx +0 -50
@@ -3,7 +3,7 @@ require "rails/generators"
|
|
3
3
|
module ReactOnRails
|
4
4
|
module Generators
|
5
5
|
class JsLintersGenerator < Rails::Generators::Base
|
6
|
-
|
6
|
+
Rails::Generators.hide_namespace(namespace)
|
7
7
|
source_root File.expand_path("../templates", __FILE__)
|
8
8
|
|
9
9
|
# NOTE: linter modules are included via template in base/base/client/package.json.tt
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "rails/generators"
|
2
|
-
|
3
|
-
include GeneratorHelper
|
2
|
+
require_relative "generator_helper"
|
4
3
|
|
5
4
|
module ReactOnRails
|
6
5
|
module Generators
|
7
6
|
class ReactNoReduxGenerator < Rails::Generators::Base
|
8
|
-
|
7
|
+
include GeneratorHelper
|
8
|
+
Rails::Generators.hide_namespace(namespace)
|
9
9
|
source_root(File.expand_path("../templates", __FILE__))
|
10
10
|
|
11
11
|
# --server-rendering
|
@@ -17,10 +17,8 @@ module ReactOnRails
|
|
17
17
|
|
18
18
|
def copy_base_files
|
19
19
|
base_path = "no_redux/base/"
|
20
|
-
|
21
|
-
|
22
|
-
copy_file(base_path + file, file)
|
23
|
-
end
|
20
|
+
file = "client/app/bundles/HelloWorld/containers/HelloWorld.jsx"
|
21
|
+
copy_file(base_path + file, file)
|
24
22
|
end
|
25
23
|
|
26
24
|
def copy_server_rendering_files_if_appropriate
|
@@ -3,7 +3,7 @@ require "rails/generators"
|
|
3
3
|
module ReactOnRails
|
4
4
|
module Generators
|
5
5
|
class ReactWithReduxGenerator < Rails::Generators::Base
|
6
|
-
|
6
|
+
Rails::Generators.hide_namespace(namespace)
|
7
7
|
source_root(File.expand_path("../templates", __FILE__))
|
8
8
|
|
9
9
|
# --server-rendering
|
@@ -23,7 +23,6 @@ module ReactOnRails
|
|
23
23
|
def copy_base_redux_files
|
24
24
|
base_path = "redux/base/"
|
25
25
|
%w(client/app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx
|
26
|
-
client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx
|
27
26
|
client/app/bundles/HelloWorld/containers/HelloWorld.jsx
|
28
27
|
client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx
|
29
28
|
client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require "rails/generators"
|
2
|
+
require_relative "generator_helper"
|
2
3
|
|
3
4
|
module ReactOnRails
|
4
5
|
module Generators
|
5
6
|
class RubyLintersGenerator < Rails::Generators::Base
|
6
|
-
|
7
|
+
include GeneratorHelper
|
8
|
+
Rails::Generators.hide_namespace(namespace)
|
7
9
|
source_root File.expand_path("../templates", __FILE__)
|
8
10
|
|
9
11
|
def add_ruby_linter_gems_to_gemfile
|
@@ -25,8 +27,8 @@ module ReactOnRails
|
|
25
27
|
%w(lib/tasks/brakeman.rake
|
26
28
|
lib/tasks/ci.rake
|
27
29
|
.rubocop.yml
|
28
|
-
.scss-lint.yml
|
29
|
-
|
30
|
+
.scss-lint.yml).each { |file| copy_file(base_path + file, file) }
|
31
|
+
template("ruby_linters/ruby-lint.yml.tt", "ruby-lint.yml")
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
// HelloWorldWidget is an arbitrary name for any "dumb" component. We do not recommend suffixing
|
2
|
+
// all your dump component names with Widget.
|
3
|
+
|
4
|
+
import React, { PropTypes } from 'react';
|
5
|
+
import _ from 'lodash';
|
6
|
+
<%- unless options.skip_bootstrap? -%>
|
7
|
+
import { Input } from 'react-bootstrap';
|
8
|
+
<%- end -%>
|
9
|
+
|
10
|
+
// Simple example of a React "dumb" component
|
11
|
+
export default class HelloWorldWidget extends React.Component {
|
12
|
+
static propTypes = {
|
13
|
+
// If you have lots of data or action properties, you should consider grouping them by
|
14
|
+
// passing two properties: "data" and "actions".
|
15
|
+
updateName: PropTypes.func.isRequired,
|
16
|
+
name: PropTypes.string.isRequired,
|
17
|
+
};
|
18
|
+
|
19
|
+
constructor(props, context) {
|
20
|
+
super(props, context);
|
21
|
+
|
22
|
+
// Uses lodash to bind all methods to the context of the object instance, otherwise
|
23
|
+
// the methods defined here would not refer to the component's class, not the component
|
24
|
+
// instance itself.
|
25
|
+
_.bindAll(this, 'handleChange');
|
26
|
+
}
|
27
|
+
|
28
|
+
// React will automatically provide us with the event `e`
|
29
|
+
handleChange(e) {
|
30
|
+
const name = e.target.value;
|
31
|
+
this.props.updateName(name);
|
32
|
+
}
|
33
|
+
|
34
|
+
render() {
|
35
|
+
const { name } = this.props;
|
36
|
+
return (
|
37
|
+
<div className="container">
|
38
|
+
<h3>
|
39
|
+
Hello, {name}!
|
40
|
+
</h3>
|
41
|
+
<hr/>
|
42
|
+
<form className="form-horizontal">
|
43
|
+
<%- if options.skip_bootstrap? -%>
|
44
|
+
<label>
|
45
|
+
Say hello to:
|
46
|
+
</label>
|
47
|
+
<input
|
48
|
+
type="text"
|
49
|
+
value={name}
|
50
|
+
onChange={this.handleChange}
|
51
|
+
/>
|
52
|
+
<%- else -%>
|
53
|
+
<Input
|
54
|
+
type="text"
|
55
|
+
labelClassName="col-sm-2"
|
56
|
+
wrapperClassName="col-sm-10"
|
57
|
+
label="Say hello to:"
|
58
|
+
value={name}
|
59
|
+
onChange={this.handleChange}
|
60
|
+
/>
|
61
|
+
<%- end -%>
|
62
|
+
</form>
|
63
|
+
</div>
|
64
|
+
);
|
65
|
+
}
|
66
|
+
}
|
@@ -55,8 +55,8 @@
|
|
55
55
|
"jquery": "^2.1.4",
|
56
56
|
"jquery-ujs": "^1.1.0-1",
|
57
57
|
"loader-utils": "^0.2.11",
|
58
|
-
<%- if options.redux? -%>
|
59
58
|
"lodash": "^3.10.1",
|
59
|
+
<%- if options.redux? -%>
|
60
60
|
"mirror-creator": "0.0.1",
|
61
61
|
<%- end -%>
|
62
62
|
"react": "^0.14.3",
|
@@ -86,13 +86,14 @@
|
|
86
86
|
<%- unless options.skip_js_linters? -%>
|
87
87
|
"eslint": "^1.10.3",
|
88
88
|
"eslint-config-airbnb": "^2.0.0",
|
89
|
+
"eslint-config-shakacode": "^0.0.1",
|
89
90
|
"eslint-plugin-react": "^3.11.3",
|
90
91
|
<%- end -%>
|
91
92
|
"express": "^4.13.3",
|
92
93
|
"file-loader": "^0.8.4",
|
93
94
|
"jade": "^1.11.0",
|
94
95
|
<%- unless options.skip_js_linters? -%>
|
95
|
-
"jscs": "^2.
|
96
|
+
"jscs": "^2.8.0",
|
96
97
|
<%- end -%>
|
97
98
|
"node-sass": "^3.4.2",
|
98
99
|
"react-transform-hmr": "^1.0.1",
|
@@ -49,7 +49,7 @@ var server = new WebpackDevServer(webpack(config), {
|
|
49
49
|
|
50
50
|
var initialName = 'Stranger';
|
51
51
|
|
52
|
-
server.app.use('/', function(req, res) {
|
52
|
+
server.app.use('/', function routePath(req, res) {
|
53
53
|
var locals = {
|
54
54
|
props: JSON.stringify(initialName),
|
55
55
|
};
|
@@ -58,7 +58,7 @@ server.app.use('/', function(req, res) {
|
|
58
58
|
res.send(html);
|
59
59
|
});
|
60
60
|
|
61
|
-
server.listen(4000, 'localhost', function(err) {
|
61
|
+
server.listen(4000, 'localhost', function onListen(err) {
|
62
62
|
if (err) console.log(err);
|
63
63
|
console.log('Listening at localhost:4000...');
|
64
64
|
});
|
@@ -16,6 +16,8 @@ module.exports = {
|
|
16
16
|
vendor: [
|
17
17
|
'babel-polyfill',
|
18
18
|
'jquery',
|
19
|
+
'react',
|
20
|
+
'react-dom',
|
19
21
|
],
|
20
22
|
|
21
23
|
// This will contain the app entry points defined by webpack.hot.config and webpack.rails.config
|
@@ -57,8 +59,8 @@ module.exports = {
|
|
57
59
|
loaders: [
|
58
60
|
|
59
61
|
// Not all apps require jQuery. Many Rails apps do, such as those using TurboLinks or bootstrap js
|
60
|
-
{test: require.resolve('jquery'), loader: 'expose?jQuery'},
|
61
|
-
{test: require.resolve('jquery'), loader: 'expose?$'},
|
62
|
+
{ test: require.resolve('jquery'), loader: 'expose?jQuery' },
|
63
|
+
{ test: require.resolve('jquery'), loader: 'expose?$' },
|
62
64
|
],
|
63
65
|
},
|
64
66
|
};
|
data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.hot.config.js.tt
CHANGED
@@ -51,7 +51,7 @@ config.module.loaders.push(
|
|
51
51
|
],
|
52
52
|
},
|
53
53
|
},
|
54
|
-
{test: /\.css$/, loader: 'style-loader!css-loader'},
|
54
|
+
{ test: /\.css$/, loader: 'style-loader!css-loader' },
|
55
55
|
{
|
56
56
|
test: /\.scss$/,
|
57
57
|
loader: 'style!css!sass?outputStyle=expanded&imagePath=/assets/images&includePaths[]=' +
|
@@ -59,11 +59,11 @@ config.module.loaders.push(
|
|
59
59
|
},
|
60
60
|
|
61
61
|
// The url-loader uses DataUrls. The file-loader emits files.
|
62
|
-
{test: /\.woff$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
|
63
|
-
{test: /\.woff2$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
|
64
|
-
{test: /\.ttf$/, loader: 'file-loader'},
|
65
|
-
{test: /\.eot$/, loader: 'file-loader'},
|
66
|
-
{test: /\.svg$/, loader: 'file-loader'}
|
62
|
+
{ test: /\.woff$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
|
63
|
+
{ test: /\.woff2$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
|
64
|
+
{ test: /\.ttf$/, loader: 'file-loader' },
|
65
|
+
{ test: /\.eot$/, loader: 'file-loader' },
|
66
|
+
{ test: /\.svg$/, loader: 'file-loader' }
|
67
67
|
);
|
68
68
|
|
69
69
|
module.exports = config;
|
data/lib/generators/react_on_rails/templates/base/base/client/webpack.client.rails.config.js
CHANGED
@@ -20,13 +20,13 @@ config.entry.vendor.unshift(
|
|
20
20
|
'es5-shim/es5-sham'
|
21
21
|
);
|
22
22
|
|
23
|
+
// jquery-ujs MUST GO AFTER jquery, so must use 'push'
|
23
24
|
config.entry.vendor.push('jquery-ujs');
|
24
25
|
|
25
26
|
// See webpack.common.config for adding modules common to both the webpack dev server and rails
|
26
|
-
|
27
27
|
config.module.loaders.push(
|
28
|
-
{test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/},
|
29
|
-
{test: require.resolve('react'), loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham'}
|
28
|
+
{ test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/ },
|
29
|
+
{ test: require.resolve('react'), loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham' }
|
30
30
|
);
|
31
31
|
|
32
32
|
module.exports = config;
|
@@ -9,7 +9,10 @@
|
|
9
9
|
},
|
10
10
|
"scripts": {
|
11
11
|
"postinstall": "cd client && npm install",
|
12
|
-
"test": "rspec && (cd client && npm run lint)"
|
12
|
+
"test": "rspec && (cd client && npm run lint)",
|
13
|
+
"node-server-hot": "cd client && npm start",
|
14
|
+
"rails-server-hot": "foreman start -f Procfile.dev-hot",
|
15
|
+
"rails-server": "foreman start -f Procfile.dev"
|
13
16
|
},
|
14
17
|
"repository": {
|
15
18
|
"type": "git",
|
@@ -12,7 +12,7 @@ module.exports = {
|
|
12
12
|
context: __dirname,
|
13
13
|
entry: [
|
14
14
|
'babel-polyfill',
|
15
|
-
'./app/bundles/HelloWorld/startup/serverRegistration'
|
15
|
+
'./app/bundles/HelloWorld/startup/serverRegistration',
|
16
16
|
],
|
17
17
|
output: {
|
18
18
|
filename: 'server-bundle.js',
|
@@ -27,13 +27,13 @@ module.exports = {
|
|
27
27
|
plugins: [
|
28
28
|
new webpack.DefinePlugin({
|
29
29
|
'process.env': {
|
30
|
-
NODE_ENV: JSON.stringify(
|
30
|
+
NODE_ENV: JSON.stringify(nodeEnv),
|
31
31
|
},
|
32
32
|
}),
|
33
33
|
],
|
34
34
|
module: {
|
35
35
|
loaders: [
|
36
|
-
{test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/},
|
36
|
+
{ test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/ },
|
37
37
|
],
|
38
38
|
},
|
39
39
|
};
|
@@ -6,27 +6,29 @@ import _ from 'lodash';
|
|
6
6
|
export default class HelloWorld extends React.Component {
|
7
7
|
static propTypes = {
|
8
8
|
name: PropTypes.string.isRequired, // this is passed from the Rails view
|
9
|
-
}
|
9
|
+
};
|
10
10
|
|
11
11
|
constructor(props, context) {
|
12
12
|
super(props, context);
|
13
13
|
|
14
|
+
// How to set initial state in ES6 class syntax
|
15
|
+
// https://facebook.github.io/react/docs/reusable-components.html#es6-classes
|
16
|
+
this.state = { name: this.props.name };
|
17
|
+
|
14
18
|
// Uses lodash to bind all methods to the context of the object instance, otherwise
|
15
19
|
// the methods defined here would not refer to the component's class, not the component
|
16
20
|
// instance itself.
|
17
|
-
_.bindAll(this, '
|
21
|
+
_.bindAll(this, 'updateName');
|
18
22
|
}
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
_updateName(name) {
|
23
|
-
this.setState({name: name});
|
24
|
+
updateName(name) {
|
25
|
+
this.setState({ name });
|
24
26
|
}
|
25
27
|
|
26
28
|
render() {
|
27
29
|
return (
|
28
30
|
<div>
|
29
|
-
<HelloWorldWidget name={this.state.name}
|
31
|
+
<HelloWorldWidget name={this.state.name} updateName={this.updateName} />
|
30
32
|
</div>
|
31
33
|
);
|
32
34
|
}
|
@@ -17,6 +17,9 @@ class HelloWorld extends React.Component {
|
|
17
17
|
dispatch: PropTypes.func.isRequired,
|
18
18
|
|
19
19
|
// This corresponds to the value used in function select above.
|
20
|
+
// We prefix all property and variable names pointing to Immutable.js objects with '$$'.
|
21
|
+
// This allows us to immediately know we don't call $$helloWorldStore['someProperty'], but
|
22
|
+
// instead use the Immutable.js `get` API for Immutable.Map
|
20
23
|
$$helloWorldStore: PropTypes.instanceOf(Immutable.Map).isRequired,
|
21
24
|
};
|
22
25
|
|
@@ -27,12 +30,14 @@ class HelloWorld extends React.Component {
|
|
27
30
|
render() {
|
28
31
|
const { dispatch, $$helloWorldStore } = this.props;
|
29
32
|
const actions = bindActionCreators(helloWorldActionCreators, dispatch);
|
33
|
+
const { updateName } = actions;
|
34
|
+
const name = $$helloWorldStore.get('name');
|
30
35
|
|
31
36
|
// This uses the ES2015 spread operator to pass properties as it is more DRY
|
32
37
|
// This is equivalent to:
|
33
38
|
// <HelloWorldWidget $$helloWorldStore={$$helloWorldStore} actions={actions} />
|
34
39
|
return (
|
35
|
-
<HelloWorldWidget {...{
|
40
|
+
<HelloWorldWidget {...{ updateName, name }} />
|
36
41
|
);
|
37
42
|
}
|
38
43
|
}
|
@@ -10,10 +10,10 @@ export default function helloWorldReducer($$state = $$initialState, action) {
|
|
10
10
|
const { type, name } = action;
|
11
11
|
|
12
12
|
switch (type) {
|
13
|
-
|
14
|
-
|
13
|
+
case actionTypes.HELLO_WORLD_NAME_UPDATE:
|
14
|
+
return $$state.set('name', name);
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
default:
|
17
|
+
return $$state;
|
18
18
|
}
|
19
19
|
}
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "react-on-rails",
|
3
|
-
"version": "2.0.0-
|
3
|
+
"version": "2.0.0-rc.1",
|
4
4
|
"description": "react-on-rails JavaScript for react_on_rails Ruby gem",
|
5
5
|
"main": "node_package/lib/ReactOnRails.js",
|
6
6
|
"directories": {
|
@@ -11,7 +11,7 @@
|
|
11
11
|
"babel": "^6.3.13",
|
12
12
|
"babel-cli": "^6.3.17",
|
13
13
|
"babel-core": "^6.3.17",
|
14
|
-
"babel-eslint": "^5.0.0-
|
14
|
+
"babel-eslint": "^5.0.0-beta6",
|
15
15
|
"babel-loader": "^6.2.0",
|
16
16
|
"babel-plugin-transform-runtime": "^6.3.13",
|
17
17
|
"babel-preset-es2015": "^6.3.13",
|
@@ -22,12 +22,14 @@
|
|
22
22
|
"babelify": "^7.2.0",
|
23
23
|
"blue-tape": "^0.1.11",
|
24
24
|
"eslint": "^1.10.3",
|
25
|
-
"eslint-config-airbnb": "^2.
|
25
|
+
"eslint-config-airbnb": "^2.1.1",
|
26
|
+
"eslint-config-shakacode": "0.0.1",
|
26
27
|
"eslint-plugin-babel": "^3.0.0",
|
27
28
|
"eslint-plugin-react": "^3.11.3",
|
28
29
|
"jscs": "^2.6.0",
|
29
30
|
"react": "^0.14.3",
|
30
31
|
"react-dom": "^0.14.3",
|
32
|
+
"react-transform-hmr": "^1.0.1",
|
31
33
|
"tap-spec": "^4.1.1",
|
32
34
|
"tape": "^4.4.0",
|
33
35
|
"webpack": "^1.12.9"
|