From 2b4231b94157d7f93bf2da183dd5ab0b4f05ed6b Mon Sep 17 00:00:00 2001 From: Ted Johansson Date: Thu, 11 Mar 2021 12:49:43 +0800 Subject: [PATCH] [Feature] Allow default: nil option without required: false for OptionsDeclaration.option --- CHANGELOG.md | 7 +++++++ Gemfile.lock | 2 +- lib/stimpack/options_declaration.rb | 22 +++++++++++++++++++--- lib/stimpack/version.rb | 2 +- spec/stimpack/options_declaration_spec.rb | 14 ++++++++++---- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2d661c..9d83437 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.5.3 + +### New features + +- Allow `default: nil` to be used without needing `required: false` for the + `OptionsDeclaration.option` method. + ## 0.5.2 ### New features diff --git a/Gemfile.lock b/Gemfile.lock index 4d2e7ce..1881b85 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - stimpack (0.5.2) + stimpack (0.5.3) activesupport (~> 6.1) GEM diff --git a/lib/stimpack/options_declaration.rb b/lib/stimpack/options_declaration.rb index f58dbf7..965c4e7 100644 --- a/lib/stimpack/options_declaration.rb +++ b/lib/stimpack/options_declaration.rb @@ -53,7 +53,7 @@ def self.extended(klass) # option :user # end # - def option(*identifiers, required: true, default: nil, private_reader: true) # rubocop:disable Metrics/MethodLength + def option(*identifiers, required: true, default: Option::MISSING_VALUE, private_reader: true) # rubocop:disable Metrics/MethodLength self.options_configuration = options_configuration.merge( identifiers.map do |identifier| [ @@ -87,6 +87,10 @@ def required_options def optional_options options_configuration.select { |_, option| option.optional? }.keys end + + def default_options + options_configuration.select { |_, option| option.default? }.keys + end end # Injects an initializer that assigns options and proxies the call to any @@ -146,25 +150,37 @@ def self.included(klass) end class Option + MISSING_VALUE = "__missing__" + def initialize(name, required:, default:) @name = name @default = default @required = required end - attr_reader :name, :default, :required + attr_reader :name def default_value + return nil unless default? + default.respond_to?(:call) ? default.() : default end def required? - required && default.nil? + required && !default? end def optional? !required? end + + def default? + default != MISSING_VALUE + end + + private + + attr_reader :default, :required end end end diff --git a/lib/stimpack/version.rb b/lib/stimpack/version.rb index 345703a..e243e1e 100644 --- a/lib/stimpack/version.rb +++ b/lib/stimpack/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Stimpack - VERSION = "0.5.2" + VERSION = "0.5.3" end diff --git a/spec/stimpack/options_declaration_spec.rb b/spec/stimpack/options_declaration_spec.rb index b4081d2..d2c6d8f 100644 --- a/spec/stimpack/options_declaration_spec.rb +++ b/spec/stimpack/options_declaration_spec.rb @@ -13,12 +13,13 @@ option :bar, required: false option :baz, private_reader: false option :qux, default: "Foo" + option :quuz, default: nil option :quux, default: -> { "Bar" } end end describe ".option" do - it { expect(service.options_configuration.size).to eq(5) } + it { expect(service.options_configuration.size).to eq(6) } it { expect(service.options_configuration.values).to all(be_a(described_class::Option)) } describe "private_reader (option)" do @@ -26,12 +27,12 @@ let(:private_instance_methods) { service.private_instance_methods(false) } it { expect(public_instance_methods).to contain_exactly(:baz) } - it { expect(private_instance_methods).to contain_exactly(:foo, :bar, :qux, :quux) } + it { expect(private_instance_methods).to contain_exactly(:foo, :bar, :qux, :quux, :quuz) } end end describe ".options" do - it { expect(service.options).to contain_exactly(:foo, :bar, :baz, :qux, :quux) } + it { expect(service.options).to contain_exactly(:foo, :bar, :baz, :qux, :quux, :quuz) } end describe ".required_options" do @@ -39,7 +40,11 @@ end describe ".optional_options" do - it { expect(service.optional_options).to contain_exactly(:bar, :qux, :quux) } + it { expect(service.optional_options).to contain_exactly(:bar, :qux, :quux, :quuz) } + end + + describe ".default_options" do + it { expect(service.default_options).to contain_exactly(:qux, :quux, :quuz) } end describe "#initialize" do @@ -86,6 +91,7 @@ context "when default option is assigned by omission" do it { expect(instance.send(:qux)).to eq("Foo") } it { expect(instance.send(:quux)).to eq("Bar") } + it { expect(instance.send(:quuz)).to eq(nil) } end end end