From 59c8344c256c8f4aa59aaeb45bc108c258a950bc Mon Sep 17 00:00:00 2001 From: Boris Rorsvort Date: Sat, 8 Aug 2015 21:50:55 +0200 Subject: [PATCH 1/4] adds es6 option to generator --- README.md | 14 ++++++++++++- lib/generators/react/component_generator.rb | 7 ++++++- lib/generators/templates/component.es6.jsx | 23 +++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 lib/generators/templates/component.es6.jsx 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 -%> From 03022278c94c85b2b11cdb1fef46a20554a6dd63 Mon Sep 17 00:00:00 2001 From: Boris Rorsvort Date: Sun, 9 Aug 2015 12:06:24 +0200 Subject: [PATCH 2/4] add some test for es6 generator --- .../es6_component_generator_test.rb | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 test/generators/es6_component_generator_test.rb diff --git a/test/generators/es6_component_generator_test.rb b/test/generators/es6_component_generator_test.rb new file mode 100644 index 00000000..6ef94a0f --- /dev/null +++ b/test/generators/es6_component_generator_test.rb @@ -0,0 +1,60 @@ +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 + + test "creates the component file" do + run_generator %w(GeneratedComponent --es6) + + assert_file filename + end + + test "creates the component file with a node argument" do + puts name + run_generator %w(GeneratedComponent name --es6) + assert_file filename, %r{name: React.PropTypes.node} + end + + test "creates the component file with various standard proptypes" do + proptypes = %w(string bool number array func number object any) + run_generator %w(GeneratedComponent) + proptypes.map { |type| "my_#{type}:#{type}"} + ["--es6"] + proptypes.each do |type| + assert_file filename, %r(my#{type.capitalize}: React.PropTypes.#{type}) + end + end + + test "creates a component file with an instanceOf property" do + run_generator %w(GeneratedComponent favorite_food:instanceOf{food} --es6) + assert_file filename, /favoriteFood: React.PropTypes.instanceOf\(Food\)/ + end + + test "creates a component file with a oneOf property" do + run_generator %w(GeneratedComponent favorite_food:oneOf{pizza,hamburgers} --es6) + assert_file filename, /favoriteFood: React.PropTypes.oneOf\(\['pizza','hamburgers'\]\)/ + end + + test "creates a component file with a oneOfType property" do + run_generator %w(GeneratedComponent favorite_food:oneOfType{string,Food} --es6) + expected_property = "favoriteFood: React.PropTypes.oneOfType([React.PropTypes.string,React.PropTypes.instanceOf(Food)])" + + assert_file filename, Regexp.new(Regexp.quote(expected_property)) + 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 From b4d4a23ddca06de7d0786b4bb16802923b94dd70 Mon Sep 17 00:00:00 2001 From: Boris Rorsvort Date: Sun, 9 Aug 2015 12:16:44 +0200 Subject: [PATCH 3/4] fix build --- test/generators/es6_component_generator_test.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/generators/es6_component_generator_test.rb b/test/generators/es6_component_generator_test.rb index 6ef94a0f..a0476fa9 100644 --- a/test/generators/es6_component_generator_test.rb +++ b/test/generators/es6_component_generator_test.rb @@ -17,7 +17,6 @@ def filename end test "creates the component file with a node argument" do - puts name run_generator %w(GeneratedComponent name --es6) assert_file filename, %r{name: React.PropTypes.node} end From 4ad2117e6b559e4387a26c94bce9cfc6564147e5 Mon Sep 17 00:00:00 2001 From: Boris Rorsvort Date: Wed, 19 Aug 2015 10:19:55 +0200 Subject: [PATCH 4/4] Simplifies test to match new behaviours --- .../es6_component_generator_test.rb | 34 ++++--------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/test/generators/es6_component_generator_test.rb b/test/generators/es6_component_generator_test.rb index a0476fa9..9431809e 100644 --- a/test/generators/es6_component_generator_test.rb +++ b/test/generators/es6_component_generator_test.rb @@ -10,40 +10,20 @@ def filename 'app/assets/javascripts/components/generated_component.es6.jsx' end - test "creates the component file" do - run_generator %w(GeneratedComponent --es6) - - assert_file filename + def class_name + 'GeneratedComponent' end - test "creates the component file with a node argument" do + test "uses es6 syntax" do run_generator %w(GeneratedComponent name --es6) - assert_file filename, %r{name: React.PropTypes.node} - end - - test "creates the component file with various standard proptypes" do - proptypes = %w(string bool number array func number object any) - run_generator %w(GeneratedComponent) + proptypes.map { |type| "my_#{type}:#{type}"} + ["--es6"] - proptypes.each do |type| - assert_file filename, %r(my#{type.capitalize}: React.PropTypes.#{type}) - end - end - test "creates a component file with an instanceOf property" do - run_generator %w(GeneratedComponent favorite_food:instanceOf{food} --es6) - assert_file filename, /favoriteFood: React.PropTypes.instanceOf\(Food\)/ + assert_file filename, /^class\s#{class_name}\sextends\sReact\.Component/ end - test "creates a component file with a oneOf property" do - run_generator %w(GeneratedComponent favorite_food:oneOf{pizza,hamburgers} --es6) - assert_file filename, /favoriteFood: React.PropTypes.oneOf\(\['pizza','hamburgers'\]\)/ - end - - test "creates a component file with a oneOfType property" do - run_generator %w(GeneratedComponent favorite_food:oneOfType{string,Food} --es6) - expected_property = "favoriteFood: React.PropTypes.oneOfType([React.PropTypes.string,React.PropTypes.instanceOf(Food)])" + test "assigns defaultProps after class definintion" do + run_generator %w(GeneratedComponent name --es6) - assert_file filename, Regexp.new(Regexp.quote(expected_property)) + assert_file filename, /\s^#{class_name}\.propTypes/ end test "generates working jsx" do