Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Support default value for optional environment variables #56

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/prius/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ module Prius
class MissingValueError < StandardError; end
class TypeMismatchError < StandardError; end
class UndeclaredNameError < StandardError; end
class InvalidLoadError < StandardError; end
end
35 changes: 16 additions & 19 deletions lib/prius/registry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ def initialize(env)
end

# See Prius.load for documentation.
def load(name, env_var: nil, type: :string, required: true)
def load(name, env_var: nil, type: :string, required: true, default: nil)
env_var = name.to_s.upcase if env_var.nil?

if required && !default.nil?
raise InvalidLoadError, "required config value #{env_var} cannot have default value"
end

value = load_value(env_var, required, default)
@registry[name] = case type
when :string then load_string(env_var, required)
when :int then load_int(env_var, required)
when :bool then load_bool(env_var, required)
when :date then load_date(env_var, required)
when :string then value
when :int then parse_int(env_var, value)
when :bool then parse_bool(env_var, value)
when :date then parse_date(env_var, value)
else raise ArgumentError, "Invalid type #{type}"
end
end
Expand All @@ -35,40 +41,31 @@ def get(name)

private

def load_string(name, required)
def load_value(name, required, default)
@env.fetch(name)
rescue KeyError
return nil unless required
return default unless required

raise MissingValueError, "config value '#{name}' not present"
end

def load_int(name, required)
value = load_string(name, required)
return value if value.nil?

def parse_int(name, value)
unless /\A[0-9]+\z/.match?(value)
raise TypeMismatchError, "'#{name}' value '#{value}' is not an integer"
end

value.to_i
end

def load_bool(name, required)
value = load_string(name, required)
return nil if value.nil?

def parse_bool(name, value)
value = value.downcase
return true if %w[yes y true t 1].include?(value)
return false if %w[no n false f 0].include?(value)

raise TypeMismatchError, "'#{name}' value '#{value}' is not a boolean"
end

def load_date(name, required)
value = load_string(name, required)
return nil if value.nil?

def parse_date(name, value)
Date.parse(value)
rescue ArgumentError
raise TypeMismatchError, "'#{name}' value '#{value}' is not a date"
Expand Down
35 changes: 33 additions & 2 deletions spec/prius/registry_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@
it "doesn't blow up" do
expect { registry.load(:name) }.to_not raise_error
end

context "but also a default value" do
it "raises an error" do
expect { registry.load(:name, default: "foo") }.
to raise_error(Prius::InvalidLoadError)
end
end
end

context "given a name that's not present in the environment" do
Expand All @@ -38,6 +45,14 @@
it "doesn't blow up" do
expect { registry.load(:slogan, required: false) }.to_not raise_error
end

context "when a default value is provided" do
it "doesn't blow up" do
expect do
registry.load(:slogan, required: false, default: "GO GO GO")
end.to_not raise_error
end
end
end
end

Expand All @@ -48,6 +63,14 @@
end
end

# TODO: Decide if default values should be strings or of the parsed type
context "when specifying a default for a non-string type" do
it "doesn't blow up" do
expect { registry.load(:blah, type: :int, required: false, default: "56") }.
to_not raise_error
end
end

context "when specifying :int as the type" do
context "given a integer value" do
it "doesn't blow up" do
Expand All @@ -74,7 +97,7 @@
expect { registry.load(:alive, type: :bool) }.to_not raise_error
end

it "stores an boolean" do
it "stores a boolean" do
registry.load(:alive, type: :bool)
expect(registry.get(:alive)).to be_a(TrueClass)
end
Expand Down Expand Up @@ -133,12 +156,20 @@
end
end

context "given a nillable name that has been loaded" do
context "given a nilable name that has been loaded" do
before { registry.load(:lightsabre, required: false) }

it "returns nil" do
expect(registry.get(:lightsabre)).to be_nil
end

context "with a default" do
before { registry.load(:lightsabre, required: false, default: "blue") }

it "returns the default" do
expect(registry.get(:lightsabre)).to eq("blue")
end
end
end
end
end