diff --git a/README.md b/README.md index a9f86de9..4f70aaeb 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,7 @@ end ### Component generator `react-rails` ships with a Rails generator to help you get started with a simple component scaffold. -You can run it using `rails generate react:component ComponentName`. +You can run it using `rails generate react:component ComponentName (--es6)`. The generator takes an optional list of arguments for default propTypes, which follow the conventions set in the [Reusable Components](http://facebook.github.io/react/docs/reusable-components.html) section of the React documentation. @@ -239,6 +239,18 @@ var Post = React.createClass({ }); ``` +#### Options + +**--es6** : Generate the same component but using cutting edge es6 class + +For example: + +```shell +rails generate react:component Label label:string --es6 +``` + +#### Arguments + The generator can use the following arguments to create basic propTypes: * any diff --git a/lib/generators/react/component_generator.rb b/lib/generators/react/component_generator.rb index 14b9682f..f585c2f5 100644 --- a/lib/generators/react/component_generator.rb +++ b/lib/generators/react/component_generator.rb @@ -50,6 +50,11 @@ class ComponentGenerator < ::Rails::Generators::NamedBase :default => [], :banner => "field[:type] field[:type] ..." + class_option :es6, + type: :boolean, + default: false, + desc: 'Output es6 class based component' + REACT_PROP_TYPES = { "node" => 'React.PropTypes.node', "bool" => 'React.PropTypes.bool', @@ -80,7 +85,7 @@ class ComponentGenerator < ::Rails::Generators::NamedBase } def create_component_file - extension = "js.jsx" + extension = options[:es6] ? "es6.jsx" : "js.jsx" file_path = File.join('app/assets/javascripts/components', "#{file_name}.#{extension}") template("component.#{extension}", file_path) end diff --git a/lib/generators/templates/component.es6.jsx b/lib/generators/templates/component.es6.jsx new file mode 100644 index 00000000..75a48094 --- /dev/null +++ b/lib/generators/templates/component.es6.jsx @@ -0,0 +1,23 @@ +class <%= file_name.camelize %> extends React.Component { + render () { +<% if attributes.size > 0 -%> + return ( +
+<% attributes.each do |attribute| -%> +
<%= attribute[:name].titleize %>: {this.props.<%= attribute[:name].camelize(:lower) %>}
+<% end -%> +
+ ); +<% else -%> + return
; +<% end -%> + } +} + +<% if attributes.size > 0 -%> +<%= file_name.camelize %>.propTypes = { +<% attributes.each_with_index do |attribute, idx| -%> + <%= attribute[:name].camelize(:lower) %>: <%= attribute[:type] %><% if (idx < attributes.length-1) %>,<% end %> +<% end -%> +}; +<% end -%> diff --git a/test/generators/es6_component_generator_test.rb b/test/generators/es6_component_generator_test.rb new file mode 100644 index 00000000..9431809e --- /dev/null +++ b/test/generators/es6_component_generator_test.rb @@ -0,0 +1,39 @@ +require 'test_helper' +require 'generators/react/component_generator' + +class Es6ComponentGeneratorTest < Rails::Generators::TestCase + destination File.join(Rails.root, 'tmp', 'component_generator_test_output') + setup :prepare_destination + tests React::Generators::ComponentGenerator + + def filename + 'app/assets/javascripts/components/generated_component.es6.jsx' + end + + def class_name + 'GeneratedComponent' + end + + test "uses es6 syntax" do + run_generator %w(GeneratedComponent name --es6) + + assert_file filename, /^class\s#{class_name}\sextends\sReact\.Component/ + end + + test "assigns defaultProps after class definintion" do + run_generator %w(GeneratedComponent name --es6) + + assert_file filename, /\s^#{class_name}\.propTypes/ + end + + test "generates working jsx" do + expected_name_div = /React\.createElement\(\s*"div",\s*null,\s*\"Name:\s*\",\s*this\.props\.name\s*\)/x + expected_shape_div = /React\.createElement\(\s*"div",\s*null,\s*\"Address:\s*\",\s*this\.props\.address\s*\)/x + + run_generator %w(GeneratedComponent name:string address:shape --es6) + jsx = React::JSX.transform(File.read(File.join(destination_root, filename))) + + assert_match(Regexp.new(expected_name_div), jsx) + assert_match(Regexp.new(expected_shape_div), jsx) + end +end