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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +2 -8
- data/Dockerfile_tests +1 -1
- data/Gemfile +68 -2
- data/README.md +21 -15
- data/Rakefile +3 -109
- data/app/assets/javascripts/react_on_rails.js +10 -0
- data/docker-compose.yml +0 -6
- data/docs/additional_reading/webpack.md +46 -0
- data/docs/generator_testing.md +20 -0
- data/lib/generators/react_on_rails/base_generator.rb +49 -9
- data/lib/generators/react_on_rails/bootstrap_generator.rb +14 -29
- data/lib/generators/react_on_rails/dev_tests_generator.rb +30 -0
- data/lib/generators/react_on_rails/install_generator.rb +14 -3
- data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +2 -3
- data/lib/generators/react_on_rails/templates/base/base/client/package.json.tt +26 -23
- data/lib/generators/react_on_rails/templates/base/base/client/{webpack.client.hot.config.js → webpack.client.hot.config.js.tt} +3 -1
- data/lib/generators/react_on_rails/templates/base/base/lib/tasks/{assets.rake → assets.rake.tt} +2 -0
- data/lib/generators/react_on_rails/templates/base/server_rendering/client/webpack.server.rails.config.js +1 -1
- data/lib/generators/react_on_rails/templates/dev_tests/.rspec +2 -0
- data/lib/generators/react_on_rails/templates/dev_tests/spec/features/hello_world_spec.rb +25 -0
- data/lib/generators/react_on_rails/templates/dev_tests/spec/rails_helper.rb +57 -0
- data/lib/generators/react_on_rails/templates/dev_tests/spec/simplecov_helper.rb +21 -0
- data/lib/generators/react_on_rails/templates/dev_tests/spec/spec_helper.rb +95 -0
- data/lib/react_on_rails/version.rb +1 -1
- data/rakelib/docker.rake +33 -0
- data/rakelib/dummy_apps.rake +29 -0
- data/rakelib/example_type.rb +160 -0
- data/rakelib/examples.rake +103 -0
- data/rakelib/examples_config.yml +19 -0
- data/rakelib/lint.rake +37 -0
- data/rakelib/run_rspec.rake +65 -0
- data/rakelib/task_helpers.rb +44 -0
- data/ruby-lint.yml +1 -0
- metadata +22 -9
- data/Dockerfile_ci +0 -12
- data/docs/generator_testing_script.md +0 -49
- 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
|
data/rakelib/docker.rake
ADDED
@@ -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
|