From 69e528349fba9ee7ad12182a3bc705a4876e5319 Mon Sep 17 00:00:00 2001 From: Chris Keele Date: Fri, 19 Jan 2018 19:05:53 -0800 Subject: [PATCH] Add base error class to new gems. Closes #6260. --- lib/bundler/cli.rb | 2 ++ lib/bundler/cli/gem.rb | 14 ++++++++ lib/bundler/templates/newgem/lib/newgem.rb.tt | 5 +++ spec/commands/newgem_spec.rb | 36 +++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 40ba1287fb5..7b0b78e6caa 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -515,6 +515,8 @@ def viz method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config gem.mit true`." method_option :test, :type => :string, :lazy_default => "rspec", :aliases => "-t", :banner => "rspec", :desc => "Generate a test directory for your library, either rspec or minitest. Set a default with `bundle config gem.test rspec`." + method_option :error_class, :type => :string, :default => "StandardError", :aliases => "-e", + :desc => "Generate a base error class for your library." def gem(name) end diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb index ebfaf75b8ca..53cea7d7549 100644 --- a/lib/bundler/cli/gem.rb +++ b/lib/bundler/cli/gem.rb @@ -28,6 +28,7 @@ def initialize(options, gem_name, thor) @target = SharedHelpers.pwd.join(gem_name) validate_ext_name if options[:ext] + validate_error_class if options[:error_class] end def run @@ -56,6 +57,7 @@ def run :test => options[:test], :ext => options[:ext], :exe => options[:exe], + :error_class => options[:error_class], :bundler_version => bundler_dependency_version, :github_username => github_username.empty? ? "[USERNAME]" : github_username } @@ -242,6 +244,18 @@ def ensure_safe_gem_name(name, constant_array) exit 1 end + def validate_error_class + error_class = options[:error_class] + + if (error = Object.const_get(error_class)) && !(error <= Exception) # rubocop:disable Style/InverseMethods + Bundler.ui.error "Invalid error class #{error_class}. Please use a class inheriting from Exception." + exit 1 + end + rescue NameError + Bundler.ui.error "Invalid class name #{error_class} for error class. Please provide an Exception subclass." + exit 1 + end + def open_editor(editor, file) thor.run(%(#{editor} "#{file}")) end diff --git a/lib/bundler/templates/newgem/lib/newgem.rb.tt b/lib/bundler/templates/newgem/lib/newgem.rb.tt index 7d8ad90ab0c..457172b403c 100644 --- a/lib/bundler/templates/newgem/lib/newgem.rb.tt +++ b/lib/bundler/templates/newgem/lib/newgem.rb.tt @@ -6,6 +6,11 @@ require "<%= config[:namespaced_path] %>/<%= config[:underscored_name] %>" <%- config[:constant_array].each_with_index do |c, i| -%> <%= " " * i %>module <%= c %> <%- end -%> +<%- if config[:error_class] -%> +<%= " " * config[:constant_array].size %>class Error < <%= config[:error_class] %> +<%= " " * config[:constant_array].size %> # Base class for your errors +<%= " " * config[:constant_array].size %>end +<%- end -%> <%= " " * config[:constant_array].size %># Your code goes here... <%- (config[:constant_array].size-1).downto(0) do |i| -%> <%= " " * i %>end diff --git a/spec/commands/newgem_spec.rb b/spec/commands/newgem_spec.rb index 1a3e8236b65..cfc82845857 100644 --- a/spec/commands/newgem_spec.rb +++ b/spec/commands/newgem_spec.rb @@ -310,6 +310,10 @@ def create_temporary_dir(dir) expect(bundled_app("test_gem/lib/test_gem.rb").read).to match(%r{require "test_gem/version"}) end + it "creates a base error class" do + expect(bundled_app("test_gem/lib/test_gem.rb").read).to include("class Error < StandardError") + end + it "runs rake without problems" do system_gems ["rake-10.0.2"] @@ -550,6 +554,38 @@ def create_temporary_dir(dir) end end + context "--error-class flag set" do + context "with valid error class name" do + it "generates a gem skeleton with error subclassing given base class" do + execute_bundle_gem("test_gem", "--error-class RuntimeError") + expect(bundled_app("test_gem/lib/test_gem.rb").read).to include("< RuntimeError") + end + end + + context "with non-error class name" do + it "fails to generate a gem skeleton" do + expect do + execute_bundle_gem("test_gem", "--error-class Enumerable") + end.to raise_error(RuntimeError, /Invalid error class/) + end + end + + context "with invalid class name" do + it "fails to generate a gem skeleton" do + expect do + execute_bundle_gem("test_gem", "--error-class qpwoeiryt") + end.to raise_error(RuntimeError, /Invalid class name/) + end + end + end + + context "--no-error-class flag set" do + it "generates a gem skeleton without error subclass" do + execute_bundle_gem("test_gem", "--no-error-class") + expect(bundled_app("test_gem/lib/test_gem.rb").read).to_not include("class Error") + end + end + context "gem naming with dashed" do let(:gem_name) { "test-gem" }