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

Cast boolean values #45

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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
6 changes: 5 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ jobs:
strategy:
matrix:
os: [ubuntu, macos]
ruby-version: ['3.1', '3.0', '2.7', '2.6', '2.5']
ruby-version:
- 3.3
- 3.2
- 3.1
- 3.0
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

steps:
- uses: actions/checkout@v2

Expand Down
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,11 @@ Gemfile.lock
pkg/*
.rspec
coverage/**
.DS_Store
.DS_Store

.ruby-gemset
.ruby-version
.tool-versions

.vscode
.idea
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
--color
--require spec_helper
8 changes: 8 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
require:
- rubocop-rake
- rubocop-rspec

AllCops:
TargetRubyVersion: 3.0
NewCops: enable

Metrics/MethodLength:
Enabled: true
Max: 11
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## [2.2.0] - 2024-11-22

- Predicate methods now cast the value to a boolean
```ruby
Global.foo.enabled # => "0"
Global.foo.enabled? # => false
```
- Dropped Ruby 2.7 support
12 changes: 11 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,15 @@

source 'https://rubygems.org'

# Specify your gem's dependencies in global.gemspec
gemspec

gem 'aws-sdk-ssm', '~> 1'
gem 'google-cloud-secret_manager', '~> 0'

gem 'rake', '>= 13'
gem 'rspec', '>= 3.0'
gem 'simplecov'

gem 'rubocop', '~> 1.68'
gem 'rubocop-rake'
gem 'rubocop-rspec'
7 changes: 1 addition & 6 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
# frozen_string_literal: true

require 'rubygems'
require 'bundler'
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did not find why these were needed.


Bundler.require
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://bundler.io/guides/bundler_setup.html

For such a small Gemfile, we’d advise you to skip Bundler.require and just require the gems by hand


require 'rspec/core/rake_task'
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
require 'rubocop/rake_task'

RSpec::Core::RakeTask.new(:spec)
Expand Down
23 changes: 8 additions & 15 deletions global.gemspec
Original file line number Diff line number Diff line change
@@ -1,31 +1,24 @@
# frozen_string_literal: true

$LOAD_PATH.push File.expand_path('lib', __dir__)
require 'global/version'
require_relative 'lib/global/version'

Gem::Specification.new do |s|
s.name = 'global'
s.version = Global::VERSION
s.required_ruby_version = '>= 3.0.0'
s.authors = ['Railsware LLC']
s.email = 'contact@railsware.com'

s.description = 'Simple way to load your configs from yaml/aws/gcp'

s.homepage = 'https://github.com/railsware/global'
s.licenses = ['MIT']
s.summary = 'Simple way to load your configs from yaml/aws/gcp'

s.metadata['rubygems_mfa_required'] = 'true'

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
s.require_paths = ['lib']

s.homepage = 'https://github.com/railsware/global'
s.licenses = ['MIT']

s.add_development_dependency 'aws-sdk-ssm', '~> 1'
s.add_development_dependency 'google-cloud-secret_manager', '~> 0'
s.add_development_dependency 'rake', '~> 12.3.1'
s.add_development_dependency 'rspec', '>= 3.0'
s.add_development_dependency 'rubocop', '~> 0.81.0'
s.add_development_dependency 'simplecov', '~> 0.16.1'

s.add_runtime_dependency 'activesupport', '>= 2.0'
s.add_dependency 'activesupport', '>= 2.0'
end
2 changes: 1 addition & 1 deletion lib/global/backend/aws_parameter_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def load_parameters_from_ssm(next_token = nil)
def build_configuration_from_parameters(parameters)
configuration = {}
parameters.each do |parameter|
parameter_parts = parameter.name[@prefix.length..-1].split(PATH_SEPARATOR).map(&:to_sym)
parameter_parts = parameter.name[@prefix.length..].split(PATH_SEPARATOR).map(&:to_sym)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rubocop autofix. applies to other as well.

param_container = parameter_parts[0..-2].reduce(configuration) do |container, part|
container[part] ||= {}
end
Expand Down
2 changes: 1 addition & 1 deletion lib/global/backend/filesystem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def get_config_by_key(config, key)
end

def load_yml_file(file)
file_contents = ERB.new(IO.read(file)).result
file_contents = ERB.new(File.read(file)).result
permitted_classes = [Date, Time, DateTime, Symbol].concat(@yaml_whitelist_classes)

if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('4')
Expand Down
2 changes: 1 addition & 1 deletion lib/global/backend/gcp_secret_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def build_configuration_from_page(page)
key_name = get_gcp_key_name(parameter)
next unless key_name.start_with?(@prefix)

parameter_parts = key_name[@prefix.length..-1].split(PATH_SEPARATOR).map(&:to_sym)
parameter_parts = key_name[@prefix.length..].split(PATH_SEPARATOR).map(&:to_sym)
param_container = parameter_parts[0..-2].reduce(configuration) do |container, part|
container[part] ||= {}
end
Expand Down
27 changes: 24 additions & 3 deletions lib/global/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ class Configuration
:member?, :[], :[]=, :to_hash, :to_json,
:inspect, :fetch

# rubocop:disable Lint/BooleanSymbol
# @see ActiveModel::Type::Boolean::FALSE_VALUES
FALSE_VALUES = [
false, 0,
'0', :'0',
'f', :f,
'F', :F,
'false', :false,
'FALSE', :FALSE,
'off', :off,
'OFF', :OFF
].to_set.freeze
private_constant :FALSE_VALUES
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FALSE_VALUES is implementation details and should not be exposed.

# rubocop:enable Lint/BooleanSymbol

def initialize(hash)
@hash = hash.respond_to?(:with_indifferent_access) ? hash.with_indifferent_access : hash
end
Expand Down Expand Up @@ -49,9 +64,10 @@ def respond_to_missing?(method_name, include_private = false)
end

def method_missing(method, *args, &block)
method = normalize_key_by_method(method)
if key?(method)
get_configuration_value(method)
normalized_method = normalize_key_by_method(method)
if key?(normalized_method)
value = get_configuration_value(normalized_method)
boolean_method?(method) ? cast_boolean(value) : value
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is what this PR is all about.

else
super
end
Expand All @@ -61,6 +77,11 @@ def boolean_method?(method)
'?' == method.to_s[-1]
end

# @see ActiveModel::Type::Boolean#cast_value
def cast_boolean(value)
!FALSE_VALUES.include?(value)
end

def normalize_key_by_method(method)
boolean_method?(method) ? method.to_s[0..-2].to_sym : method
end
Expand Down
2 changes: 1 addition & 1 deletion lib/global/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module Global

VERSION = '2.1.0'
VERSION = '2.2.0'

end
12 changes: 6 additions & 6 deletions spec/global/backend/aws_parameter_store_spec.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# frozen_string_literal: true

require 'spec_helper'
require 'aws-sdk-ssm'
require 'global/backend/aws_parameter_store'

RSpec.describe Global::Backend::AwsParameterStore do
subject(:parameter_store) do
described_class.new(prefix: '/testapp/', client: client)
end
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed rubocop abuses. applies to other spec files.


let(:client) do
Aws::SSM::Client.new(stub_responses: true)
end
subject do
described_class.new(prefix: '/testapp/', client: client)
end

it 'reads parameters from the parameter store' do
it 'reads parameters from the parameter store' do # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
client.stub_responses(
:get_parameters_by_path,
[
Expand All @@ -37,7 +37,7 @@
}
]
)
expect(subject.load).to eq(
expect(parameter_store.load).to eq(
foo: 'foo-value',
bar: {
baz: 'baz-value',
Expand Down
33 changes: 15 additions & 18 deletions spec/global/backend/gcp_secret_manager_spec.rb
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
# frozen_string_literal: true

require 'spec_helper'
require 'google/cloud/secret_manager'
require 'global/backend/gcp_secret_manager'

RSpec.describe Global::Backend::GcpSecretManager do
let(:client) { double }

subject do
subject(:secret_manager) do
described_class.new(prefix: 'prod-myapp-', client: client, project_id: 'example')
end

before do
@match_item = double
allow(@match_item).to receive(:name).and_return('prod-myapp-example-test_key')
let(:client) { double }

@secret_data = double
allow(@secret_data).to receive_message_chain(:payload, :data).and_return('secret value')
before do
# rubocop:disable RSpec/VerifiedDoubles
match_item = double(name: 'prod-myapp-example-test_key')
not_match_item = double(name: 'different_key')

@not_match_item = double
allow(@not_match_item).to receive(:name).and_return('different_key')
secret_data = double(data: 'secret value')
secret_version_response = double(payload: secret_data)

@list = double
allow(@list).to receive(:next_page_token).and_return('')
allow(@list).to receive(:each).and_yield(@match_item).and_yield(@not_match_item)
list = double
allow(list).to receive(:next_page_token).and_return('')
allow(list).to receive(:each).and_yield(match_item).and_yield(not_match_item)

allow(client).to receive(:project_path).and_return('projects/example')
allow(client).to receive(:secret_version_path)
.with(project: 'example', secret: 'prod-myapp-example-test_key', secret_version: 'latest')
.and_return('some_key_path')
allow(client).to receive(:access_secret_version).with(name: 'some_key_path').and_return(@secret_data)
allow(client).to receive(:list_secrets).and_return(@list)
allow(client).to receive(:access_secret_version).with(name: 'some_key_path').and_return(secret_version_response)
allow(client).to receive_messages(project_path: 'projects/example', list_secrets: list)
# rubocop:enable RSpec/VerifiedDoubles
end

it 'reads parameters from the secret manager' do
expect(subject.load).to eq({ example: { test_key: 'secret value' }})
expect(secret_manager.load).to eq({ example: { test_key: 'secret value' }})
end
end
Loading
Loading