react_on_rails 1.1.1 → 1.2.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1 -0
  4. data/.travis.yml +2 -8
  5. data/Dockerfile_tests +1 -1
  6. data/Gemfile +68 -2
  7. data/README.md +21 -15
  8. data/Rakefile +3 -109
  9. data/app/assets/javascripts/react_on_rails.js +10 -0
  10. data/docker-compose.yml +0 -6
  11. data/docs/additional_reading/webpack.md +46 -0
  12. data/docs/generator_testing.md +20 -0
  13. data/lib/generators/react_on_rails/base_generator.rb +49 -9
  14. data/lib/generators/react_on_rails/bootstrap_generator.rb +14 -29
  15. data/lib/generators/react_on_rails/dev_tests_generator.rb +30 -0
  16. data/lib/generators/react_on_rails/install_generator.rb +14 -3
  17. data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +2 -3
  18. data/lib/generators/react_on_rails/templates/base/base/client/package.json.tt +26 -23
  19. data/lib/generators/react_on_rails/templates/base/base/client/{webpack.client.hot.config.js → webpack.client.hot.config.js.tt} +3 -1
  20. data/lib/generators/react_on_rails/templates/base/base/lib/tasks/{assets.rake → assets.rake.tt} +2 -0
  21. data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +1 -1
  22. data/lib/generators/react_on_rails/templates/dev_tests/.rspec +2 -0
  23. data/lib/generators/react_on_rails/templates/dev_tests/spec/features/hello_world_spec.rb +25 -0
  24. data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +57 -0
  25. data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +21 -0
  26. data/lib/generators/react_on_rails/templates/dev_tests/spec/spec_helper.rb +95 -0
  27. data/lib/react_on_rails/version.rb +1 -1
  28. data/rakelib/docker.rake +33 -0
  29. data/rakelib/dummy_apps.rake +29 -0
  30. data/rakelib/example_type.rb +160 -0
  31. data/rakelib/examples.rake +103 -0
  32. data/rakelib/examples_config.yml +19 -0
  33. data/rakelib/lint.rake +37 -0
  34. data/rakelib/run_rspec.rake +65 -0
  35. data/rakelib/task_helpers.rb +44 -0
  36. data/ruby-lint.yml +1 -0
  37. metadata +22 -9
  38. data/Dockerfile_ci +0 -12
  39. data/docs/generator_testing_script.md +0 -49
  40. data/lib/generators/react_on_rails/templates/client/README.md +0 -97
@@ -0,0 +1,21 @@
1
+ # Starts SimpleCov for code coverage.
2
+
3
+ if ENV["COVERAGE"]
4
+ require "simplecov"
5
+
6
+ # Using a command name prevents results from getting clobbered by other test suites
7
+ example_name = File.basename(File.expand_path("../../../.", __FILE__))
8
+ SimpleCov.command_name(example_name)
9
+
10
+ SimpleCov.start("rails") do
11
+ # Consider the entire gem project as the root
12
+ # (typically this will be the folder named "react_on_rails")
13
+ gem_root_path = File.expand_path("../../../../.", __FILE__)
14
+ root gem_root_path
15
+
16
+ # Don't report anything that has "spec" in the path
17
+ add_filter do |src|
18
+ src.filename =~ %r{\/spec\/}
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,95 @@
1
+ # This file was generated by the `rails generate rspec:install` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # The settings below are suggested to provide a good initial experience
44
+ # with RSpec, but feel free to customize to your heart's content.
45
+ # rubocop:disable Style/BlockComments
46
+ =begin
47
+
48
+ # These two settings work together to allow you to limit a spec run
49
+ # to individual examples or groups you care about by tagging them with
50
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
51
+ # get run.
52
+ config.filter_run :focus
53
+ config.run_all_when_everything_filtered = true
54
+
55
+ # Allows RSpec to persist some state between runs in order to support
56
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
57
+ # you configure your source control system to ignore this file.
58
+ config.example_status_persistence_file_path = "spec/examples.txt"
59
+
60
+ # Limits the available syntax to the non-monkey patched syntax that is
61
+ # recommended. For more details, see:
62
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
63
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
64
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
65
+ config.disable_monkey_patching!
66
+
67
+ # Many RSpec users commonly either run the entire suite or an individual
68
+ # file, and it's useful to allow more verbose output when running an
69
+ # individual spec file.
70
+ if config.files_to_run.one?
71
+ # Use the documentation formatter for detailed output,
72
+ # unless a formatter has already been configured
73
+ # (e.g. via a command-line flag).
74
+ config.default_formatter = 'doc'
75
+ end
76
+
77
+ # Print the 10 slowest examples and example groups at the
78
+ # end of the spec run, to help surface which specs are running
79
+ # particularly slow.
80
+ config.profile_examples = 10
81
+
82
+ # Run specs in random order to surface order dependencies. If you find an
83
+ # order dependency and want to debug it, you can fix the order by providing
84
+ # the seed, which is printed after each run.
85
+ # --seed 1234
86
+ config.order = :random
87
+
88
+ # Seed global randomization in this process using the `--seed` CLI option.
89
+ # Setting this allows you to use `--seed` to deterministically reproduce
90
+ # test failures related to randomization by passing the same `--seed` value
91
+ # as the one that triggered the failure.
92
+ Kernel.srand config.seed
93
+ =end
94
+ end
95
+ # rubocop:enable Style/BlockComments
@@ -1,3 +1,3 @@
1
1
  module ReactOnRails
2
- VERSION = "1.1.1"
2
+ VERSION = "1.2.0.rc1"
3
3
  end
@@ -0,0 +1,33 @@
1
+ namespace :docker do
2
+ desc "Run Rubocop linter from docker"
3
+ task :rubocop do
4
+ sh "docker-compose run lint rake lint:rubocop"
5
+ end
6
+
7
+ desc "Run ruby-lint linter from docker"
8
+ task :ruby do
9
+ sh "docker-compose run lint rake lint:ruby"
10
+ end
11
+
12
+ desc "Run scss-lint linter from docker"
13
+ task :scss do
14
+ sh "docker-compose run lint rake lint:scss"
15
+ end
16
+
17
+ desc "Run eslint linter from docker"
18
+ task :eslint do
19
+ sh "docker-compose run lint rake lint:eslint"
20
+ end
21
+
22
+ desc "Run jscs linter from docker"
23
+ task :jscs do
24
+ sh "docker-compose run lint rake lint:jscs"
25
+ end
26
+ desc "Run all linting from docker"
27
+ task :lint do
28
+ sh "docker-compose run lint rake lint"
29
+ end
30
+ end
31
+
32
+ desc "Runs all linters from docker. Run `rake -D docker` to see all available lint options"
33
+ task docker: ["docker:lint"]
@@ -0,0 +1,29 @@
1
+ require_relative "task_helpers"
2
+ include ReactOnRails::TaskHelpers
3
+
4
+ namespace :dummy_apps do
5
+ task :dummy_app do
6
+ dummy_app_dir = File.join(gem_root, "spec/dummy")
7
+ bundle_install_in(dummy_app_dir)
8
+ dummy_app_client_dir = File.join(dummy_app_dir, "client")
9
+ sh_in_dir(dummy_app_client_dir, ["npm install",
10
+ "$(npm bin)/webpack --config webpack.server.js",
11
+ "$(npm bin)/webpack --config webpack.client.js"])
12
+ end
13
+
14
+ task :dummy_react_013_app do
15
+ dummy_app_dir = File.join(gem_root, "spec/dummy-react-013")
16
+ bundle_install_in(dummy_app_dir)
17
+ dummy_app_client_dir = File.join(dummy_app_dir, "client")
18
+ sh_in_dir(dummy_app_client_dir, ["npm install",
19
+ "$(npm bin)/webpack --config webpack.server.js",
20
+ "$(npm bin)/webpack --config webpack.client.js"])
21
+ end
22
+
23
+ task dummy_apps: [:dummy_app, :dummy_react_013_app] do
24
+ puts "Prepared all Dummy Apps"
25
+ end
26
+ end
27
+
28
+ desc "Prepares all dummy apps by installing dependencies"
29
+ task dummy_apps: ["dummy_apps:dummy_apps"]
@@ -0,0 +1,160 @@
1
+ require "rake"
2
+ require "pathname"
3
+
4
+ require_relative "task_helpers"
5
+
6
+ # Defines the ExampleType class, where each object represents a unique type of example
7
+ # app that we can generate.
8
+ module ReactOnRails
9
+ module TaskHelpers
10
+ class ExampleType
11
+ def self.all
12
+ @example_types ||= []
13
+ end
14
+
15
+ def self.namespace_name
16
+ "examples"
17
+ end
18
+
19
+ attr_reader :name, :generator_options
20
+
21
+ def initialize(name:, generator_options:)
22
+ @name = name
23
+ @generator_options = generator_options
24
+ self.class.all << self
25
+ end
26
+
27
+ def name_pretty
28
+ "#{@name} example app"
29
+ end
30
+
31
+ def server_rendering?
32
+ generator_options.include?("--server-rendering")
33
+ end
34
+
35
+ def dir
36
+ File.join(examples_dir, name)
37
+ end
38
+
39
+ def dir_exist?
40
+ Dir.exist?(dir)
41
+ end
42
+
43
+ def client_dir
44
+ File.join(dir, "client")
45
+ end
46
+
47
+ def source_package_json
48
+ File.join(gem_root, "lib/generators/react_on_rails/templates/base/base/client/package.json.tt")
49
+ end
50
+
51
+ def node_modules_dir
52
+ File.join(client_dir, "node_modules")
53
+ end
54
+
55
+ def webpack_bundles_dir
56
+ File.join(dir, "app", "assets", "javascripts", "generated")
57
+ end
58
+
59
+ def webpack_bundles
60
+ bundles = []
61
+ bundles << File.join(webpack_bundles_dir, "app-bundle.js")
62
+ bundles << File.join(webpack_bundles_dir, "server-bundle.js") if server_rendering?
63
+ bundles << File.join(webpack_bundles_dir, "vendor-bundle.js")
64
+ end
65
+
66
+ def gemfile
67
+ File.join(dir, "Gemfile")
68
+ end
69
+
70
+ def gemfile_lock
71
+ "#{gemfile}.lock"
72
+ end
73
+
74
+ def package_json
75
+ File.join(client_dir, "package.json")
76
+ end
77
+
78
+ # Gems we need to add to the Gemfile before bundle installing
79
+ def required_gems
80
+ relative_gem_root = Pathname(gem_root).relative_path_from(Pathname(dir))
81
+ ["gem 'react_on_rails', path: '#{relative_gem_root}'"]
82
+ end
83
+
84
+ # Options we pass when running `rails new` from the command-line
85
+ def rails_options
86
+ "--skip-bundle --skip-spring --skip-git --skip-test-unit --skip-active-record"
87
+ end
88
+
89
+ # Methods for retrieving the name of a task specific to the example type
90
+ %w(gen prepare clean clobber npm_install build_webpack_bundles).each do |task_type|
91
+ method = "#{task_type}_task_name" # ex: `clean_task_name`
92
+ task_name = "#{task_type}_#{name}" # ex: `clean_basic`
93
+
94
+ define_method(method) { "#{self.class.namespace_name}:#{task_name}" }
95
+ define_method("#{method}_short") { task_name }
96
+ end
97
+
98
+ def rspec_task_name_short
99
+ "example_#{name}"
100
+ end
101
+
102
+ def rspec_task_name
103
+ "run_rspec:#{rspec_task_name_short}"
104
+ end
105
+
106
+ def source_files
107
+ FileList.new(all_files_in_dir(generators_source_dir))
108
+ end
109
+
110
+ # Note: we need to explicitly declare a file we know is supposed to be there
111
+ # to indicate that the example is in need of being rebuilt in the case of its absence.
112
+ def generated_files
113
+ FileList.new(all_files_in_dir(dir)) do |fl|
114
+ fl.include(gemfile) # explicitly declared file (dependency of Gemfile.lock)
115
+ fl.include(package_json) # explicitly declared file (dependency of NPM Install)
116
+ fl.exclude(%r{client(/node_modules(.+)?)?$}) # leave node_modules folder
117
+ end
118
+ end
119
+
120
+ def generated_client_files
121
+ generated_files.exclude { |f| !f.start_with?(client_dir) }
122
+ end
123
+
124
+ # generated files plus explicitly included files resulting from running
125
+ # bundle install, npm install, and generating the webpack bundles
126
+ def prepared_files
127
+ generated_files
128
+ .include(webpack_bundles)
129
+ .include(node_modules_dir)
130
+ .include(gemfile_lock)
131
+ end
132
+
133
+ def clean_files
134
+ generated_files
135
+ end
136
+
137
+ # Assumes we are inside client folder
138
+ def build_webpack_bundles_shell_commands
139
+ webpack_command = File.join("$(npm bin)", "webpack")
140
+ shell_commands = []
141
+ shell_commands << "#{webpack_command} --config webpack.server.rails.config.js" if server_rendering?
142
+ shell_commands << "#{webpack_command} --config webpack.client.rails.config.js"
143
+ end
144
+
145
+ # Assumes we are inside a rails app's folder and necessary gems have been installed
146
+ def generator_shell_commands
147
+ shell_commands = []
148
+ shell_commands << "rails generate react_on_rails:install #{generator_options}"
149
+ shell_commands << "rails generate react_on_rails:dev_tests #{generator_options}"
150
+ end
151
+
152
+ private
153
+
154
+ # Defines globs that scoop up all files (including dotfiles) in given directory
155
+ def all_files_in_dir(p_dir)
156
+ [File.join(p_dir, "**", "*"), File.join(p_dir, "**", ".*")]
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,103 @@
1
+ # Defines tasks related to generating example apps using the gem's generator.
2
+ # Allows us to create and test apps generated using a wide range of options.
3
+ #
4
+ # Also see example_type.rb
5
+
6
+ require "yaml"
7
+ require_relative "example_type"
8
+ require_relative "task_helpers"
9
+ include ReactOnRails::TaskHelpers
10
+
11
+ namespace :examples do
12
+ # Loads data from examples_config.yml and instantiates corresponding ExampleType objects
13
+ examples_config_file = File.expand_path("../examples_config.yml", __FILE__)
14
+ examples_config = symbolize_keys(YAML.load(File.read(examples_config_file)))
15
+ examples_config[:example_type_data].each { |example_type_data| ExampleType.new(symbolize_keys(example_type_data)) }
16
+
17
+ # Define tasks for each example type
18
+ ExampleType.all.each do |example_type|
19
+ # GENERATED FILES
20
+ example_type.generated_files.each do |f|
21
+ file f => example_type.source_files do
22
+ Rake::Task[example_type.gen_task_name].invoke
23
+ end
24
+ end
25
+
26
+ # GEMFILE.LOCK
27
+ file example_type.gemfile_lock => example_type.gemfile do
28
+ bundle_install_in(example_type.dir)
29
+ end
30
+
31
+ # WEBPACK BUNDLES
32
+ example_type.webpack_bundles.each do |f|
33
+ file f => example_type.generated_client_files do
34
+ Rake::Task[example_type.build_webpack_bundles_task_name].invoke
35
+ end
36
+ end
37
+
38
+ # BUILD WEBPACK BUNDLES
39
+ task example_type.build_webpack_bundles_task_name_short => example_type.npm_install_task_name do
40
+ sh_in_dir(example_type.client_dir, example_type.build_webpack_bundles_shell_commands)
41
+ end
42
+
43
+ # NPM INSTALL
44
+ task example_type.npm_install_task_name_short => example_type.package_json do
45
+ unless uptodate?(example_type.node_modules_dir, [example_type.source_package_json])
46
+ sh_in_dir(example_type.client_dir, "npm install")
47
+ end
48
+ end
49
+
50
+ # CLEAN
51
+ desc "Cleans #{example_type.name_pretty}"
52
+ task example_type.clean_task_name_short do
53
+ example_type.clean_files.each { |f| rm_rf(f) }
54
+ end
55
+
56
+ # CLOBBER
57
+ desc "Clobbers (deletes) #{example_type.name_pretty}"
58
+ task example_type.clobber_task_name_short do
59
+ rm_rf(example_type.dir)
60
+ end
61
+
62
+ # GENERATE
63
+ desc "Generates #{example_type.name_pretty}"
64
+ task example_type.gen_task_name_short => example_type.clean_task_name do
65
+ mkdir_p(example_type.dir)
66
+ sh_in_dir(examples_dir, "rails new #{example_type.name} #{example_type.rails_options}")
67
+ append_to_gemfile(example_type.gemfile, example_type.required_gems)
68
+ bundle_install_in(example_type.dir)
69
+ sh_in_dir(example_type.dir, example_type.generator_shell_commands)
70
+ end
71
+
72
+ # PREPARE
73
+ desc "Prepares #{example_type.name_pretty} (generates example, `npm install`s, and generates webpack bundles)"
74
+ multitask example_type.prepare_task_name_short => example_type.prepared_files
75
+ end
76
+
77
+ desc "Cleans all example apps"
78
+ multitask clean: ExampleType.all.map(&:clean_task_name)
79
+
80
+ desc "Clobbers (deletes) all example apps"
81
+ task :clobber do
82
+ rm_rf(examples_dir)
83
+ end
84
+
85
+ desc "Generates all example apps"
86
+ multitask gen_all: ExampleType.all.map(&:gen_task_name)
87
+
88
+ desc "Prepares all example apps"
89
+ multitask prepare_all: ExampleType.all.map(&:prepare_task_name)
90
+ end
91
+
92
+ desc "Prepares all example apps. Run `rake -D examples` to see all available options"
93
+ multitask examples: ["examples:prepare_all"]
94
+
95
+ private
96
+
97
+ # Appends each string in an array as a new line of text in the given Gemfile.
98
+ # Automatically adds line returns.
99
+ def append_to_gemfile(gemfile, lines)
100
+ old_text = File.read(gemfile)
101
+ new_text = lines.reduce(old_text) { |a, e| a << "#{e}\n" }
102
+ File.open(gemfile, "w") { |f| f.puts(new_text) }
103
+ end