Skip to content

Commit c19866e

Browse files
committed
Add option to configure Zeitwerk in new gems
Add a question to configure Zeitwerk when creating new gems (false by default). It also supports a --zeitwerk flag to do it: bundle gem mygem --zeitwerk
1 parent d57d302 commit c19866e

File tree

7 files changed

+77
-3
lines changed

7 files changed

+77
-3
lines changed

bundler/lib/bundler/cli.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ def viz
549549
desc: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
550550
method_option :ext, type: :string, desc: "Generate the boilerplate for C extension code.", enum: EXTENSIONS
551551
method_option :git, type: :boolean, default: true, desc: "Initialize a git repo inside your library."
552+
method_option :zeitwerk, type: :boolean, desc: "Configure Zeitwerk as the class loader. Set a default with `bundle config set --global gem.zeitwerk true`."
552553
method_option :mit, type: :boolean, desc: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
553554
method_option :rubocop, type: :boolean, desc: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
554555
method_option :changelog, type: :boolean, desc: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."

bundler/lib/bundler/cli/gem.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ def run
145145
config[:ci_config_path] = ".circleci "
146146
end
147147

148+
if ask_and_set(:zeitwerk, "Do you want to use Zeitwerk to load classes?",
149+
"With Zeitwerk (https://github.com/fxn/zeitwerk), Ruby can load classes automatically " \
150+
"based on name conventions so that you don't have to require files manually.")
151+
config[:zeitwerk] = true
152+
end
153+
148154
if ask_and_set(:mit, "Do you want to license your code permissively under the MIT license?",
149155
"This means that any other developer or company will be legally allowed to use your code " \
150156
"for free as long as they admit you created it. You can read more about the MIT license " \

bundler/lib/bundler/templates/newgem/lib/newgem.rb.tt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ require_relative "<%= File.basename(config[:namespaced_path]) %>/version"
44
<%- if config[:ext] -%>
55
require_relative "<%= File.basename(config[:namespaced_path]) %>/<%= config[:underscored_name] %>"
66
<%- end -%>
7+
<%- if config[:zeitwerk] -%>
8+
9+
require "zeitwerk"
10+
loader = Zeitwerk::Loader.for_gem
11+
loader.setup
12+
<%- end -%>
713

814
<%- config[:constant_array].each_with_index do |c, i| -%>
915
<%= " " * i %>module <%= c %>

bundler/lib/bundler/templates/newgem/newgem.gemspec.tt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ Gem::Specification.new do |spec|
4343

4444
# Uncomment to register a new dependency of your gem
4545
# spec.add_dependency "example-gem", "~> 1.0"
46+
<%- if config[:zeitwerk] -%>
47+
spec.add_dependency "zeitwerk"
48+
<%- end -%>
4649
<%- if config[:ext] == 'rust' -%>
4750
spec.add_dependency "rb_sys", "~> 0.9.91"
4851
<%- end -%>

bundler/spec/bundler/gem_helper_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
before(:each) do
1212
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__LINTER" => "false",
13-
"BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
13+
"BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__ZEITWERK" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
1414
git("config --global init.defaultBranch main")
1515
bundle "gem #{app_name}"
1616
prepare_gemspec(app_gemspec_path)

bundler/spec/commands/newgem_spec.rb

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def bundle_exec_standardrb
3838
git("config --global github.user bundleuser")
3939

4040
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__LINTER" => "false",
41-
"BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
41+
"BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__ZEITWERK" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
4242
end
4343

4444
describe "git repo initialization" do
@@ -74,6 +74,32 @@ def bundle_exec_standardrb
7474
end
7575
end
7676

77+
shared_examples_for "--zeitwerk flag" do
78+
before do
79+
bundle "gem #{gem_name} --zeitwerk"
80+
end
81+
it "configures zeitwerk" do
82+
gem_skeleton_assertions
83+
expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.add_dependency "zeitwerk"')
84+
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to include <<~RUBY
85+
require "zeitwerk"
86+
loader = Zeitwerk::Loader.for_gem
87+
loader.setup
88+
RUBY
89+
end
90+
end
91+
92+
shared_examples_for "--no-zeitwerk flag" do
93+
before do
94+
bundle "gem #{gem_name} --no-zeitwerk"
95+
end
96+
it "does not configure zeitwerk" do
97+
gem_skeleton_assertions
98+
expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to_not include('spec.add_dependency "zeitwerk"')
99+
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to_not include('require "zeitwerk"')
100+
end
101+
end
102+
77103
shared_examples_for "--mit flag" do
78104
before do
79105
bundle "gem #{gem_name} --mit"
@@ -1408,6 +1434,28 @@ def create_temporary_dir(dir)
14081434
end
14091435
end
14101436

1437+
context "testing --zeitwerk option against bundle config settings" do
1438+
let(:gem_name) { "test-gem" }
1439+
1440+
let(:require_path) { "test/gem" }
1441+
1442+
context "with zeitwerk option in bundle config settings set to true" do
1443+
before do
1444+
global_config "BUNDLE_GEM__ZEITWERK" => "true"
1445+
end
1446+
it_behaves_like "--zeitwerk flag"
1447+
it_behaves_like "--no-zeitwerk flag"
1448+
end
1449+
1450+
context "with zeitwerk option in bundle config settings set to false" do
1451+
before do
1452+
global_config "BUNDLE_GEM__ZEITWERK" => "false"
1453+
end
1454+
it_behaves_like "--zeitwerk flag"
1455+
it_behaves_like "--no-zeitwerk flag"
1456+
end
1457+
end
1458+
14111459
context "testing --github-username option against git and bundle config settings" do
14121460
context "without git config set" do
14131461
before do
@@ -1716,6 +1764,16 @@ def create_temporary_dir(dir)
17161764
expect(bundled_app("foobar/.github/workflows/main.yml")).to exist
17171765
end
17181766

1767+
it "asks about Zeitwerk" do
1768+
global_config "BUNDLE_GEM__ZEITWERK" => nil
1769+
1770+
bundle "gem foobar" do |input, _, _|
1771+
input.puts "yes"
1772+
end
1773+
1774+
expect(bundled_app("foobar/foobar.gemspec").read).to include('spec.add_dependency "zeitwerk"')
1775+
end
1776+
17191777
it "asks about MIT license" do
17201778
global_config "BUNDLE_GEM__MIT" => nil
17211779

bundler/spec/other/major_deprecation_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@
621621
describe "deprecating rubocop" do
622622
before do
623623
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false",
624-
"BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
624+
"BUNDLE_GEM__ZEITWERK" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
625625
end
626626

627627
context "bundle gem --rubocop" do

0 commit comments

Comments
 (0)