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

Adds Sorbet and basic type coverage #6

Merged
merged 6 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
28 changes: 27 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,31 @@ jobs:
- name: Run RSspec
run: bundle exec rspec --format documentation

- name: Run Sorbet Typechecks
run: bundle exec spoom tc
lint:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v3

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2

- uses: actions/cache@v3
with:
path: vendor/bundle
key: ${{ runner.os }}-3.2-gems-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gems-

- name: bundle install
run: |
gem install bundler
bundle config path vendor/bundle
bundle install -j $(getconf _NPROCESSORS_ONLN) --retry 3

- name: Run Rubocop
run: bundle exec rubocop
run: bundle exec rubocop --ignore-unrecognized-cops
8 changes: 8 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
inherit_from: .rubocop_todo.yml

Style/FileName:
Enabled: false

Gemspec/RequiredRubyVersion:
Enabled: false

AllCops:
Exclude:
- 'bin/*'
- 'spec/*'
- 'sorbet/*'
12 changes: 12 additions & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2023-07-17 15:39:56 UTC using RuboCop version 1.54.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 1
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Max: 12
20 changes: 20 additions & 0 deletions bin/lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env ruby

require 'English'

unless system('bundle exec rubocop --parallel --ignore-unrecognized-cops')
puts $CHILD_STATUS
exit(1)
end

unless system('bundle exec spoom tc')
puts $CHILD_STATUS
exit(1)
end

unless system('bundle exec rspec --format documentation')
puts $CHILD_STATUS
exit(1)
end

puts "\n\n✅ ALL GOOD!"
27 changes: 27 additions & 0 deletions bin/spoom
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'spoom' is installed as part of a gem, and
# this file is here to facilitate running it.
#

ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)

bundle_binstub = File.expand_path("bundle", __dir__)

if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end

require "rubygems"
require "bundler/setup"

load Gem.bin_path("spoom", "spoom")
27 changes: 27 additions & 0 deletions bin/tapioca
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'tapioca' is installed as part of a gem, and
# this file is here to facilitate running it.
#

ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)

bundle_binstub = File.expand_path("bundle", __dir__)

if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end

require "rubygems"
require "bundler/setup"

load Gem.bin_path("tapioca", "tapioca")
10 changes: 7 additions & 3 deletions lib/money-distributed.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# typed: strict
# frozen_string_literal: true

require 'money/distributed/storage'
require 'money/distributed/fetcher/base'
require 'money/distributed/fetcher/file'
require 'sorbet-runtime'
require 'redis'
require 'connection_pool'
require 'money'

Dir[File.join(__dir__, './**/*', '*.rb')].each { require(_1) }
3 changes: 1 addition & 2 deletions lib/money/distributed/fetcher/base.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# typed: false
# frozen_string_literal: true

require 'money'

class Money
module Distributed
module Fetcher
Expand Down
13 changes: 12 additions & 1 deletion lib/money/distributed/fetcher/file.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# typed: strict
# frozen_string_literal: true

require 'json'
Expand All @@ -9,19 +10,29 @@ module Distributed
module Fetcher
# Fetcher that loads rates from a file
class File
extend T::Sig
include Base

sig do
params(
file_path: T.any(String, Pathname),
bank: T.untyped
).void
end
def initialize(file_path, bank = nil)
super(bank)
@file_path = file_path
end

private

sig { returns(T::Hash[String, BigDecimal]) }
def exchange_rates
::File.open(@file_path).read.split("\n").each_with_object({}) do |line, h|
code_rate = line.split(' ')
h[code_rate[0]] = BigDecimal(code_rate[1])
currency = T.cast(code_rate[0], String)
rate = T.cast(code_rate[1], T.any(Integer, Float, Rational, BigDecimal, String))
h[currency] = BigDecimal(rate)
end
end
end
Expand Down
25 changes: 19 additions & 6 deletions lib/money/distributed/redis.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
# typed: true
# frozen_string_literal: true

require 'redis'
require 'connection_pool'

class Money
module Distributed
# Wrapper over different parameters that can be provided for redis
class Redis
extend T::Sig

sig do
params(
redis: T.any(::Redis, ConnectionPool, Hash, Proc)
).void
end
def initialize(redis)
@redis_proc = build_redis_proc(redis)
end

sig do
params(
block: T.proc.returns(T.untyped)
).returns(T.untyped)
end
def exec(&block)
@redis_proc.call(&block)
end

private

# rubocop: disable Metrics/MethodLength
sig do
params(
redis: T.any(::Redis, ConnectionPool, Hash, Proc)
).returns(Proc)
end
def build_redis_proc(redis)
case redis
when ::Redis
Expand All @@ -29,10 +43,9 @@ def build_redis_proc(redis)
when Proc
redis
else
raise ArgumentError, 'Redis, ConnectionPool, Hash or Proc is required'
T.absurd(redis)
end
end
# rubocop: enable Metrics/MethodLength
end
end
end
4 changes: 1 addition & 3 deletions lib/money/distributed/storage.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# typed: true
# frozen_string_literal: true

require 'bigdecimal'
require 'money/distributed/redis'

class Money
module Distributed
# Storage for `Money::Bank::VariableExchange` that stores rates in Redis
Expand Down
1 change: 1 addition & 0 deletions lib/money/distributed/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# typed: true
# frozen_string_literal: true

class Money
Expand Down
27 changes: 16 additions & 11 deletions money-distributed.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,27 @@ Gem::Specification.new do |spec|
spec.homepage = 'https://github.com/DarthSim/money-distributed'
spec.license = 'MIT'

spec.required_ruby_version = '>= 2.5'
spec.required_ruby_version = '>= 3.0'
spec.files = Dir[
'lib/**/*',
'sorbet/rbi/dsl/**/*.rbi',
'sorbet/rbi/shims/**/*.rbi',
'LICENSE',
'README.md',
]

spec.files = `git ls-files -z`.split("\x0").reject do |f|
f.match(%r{^(test|spec|features)/})
end

spec.bindir = 'exe'
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']
spec.add_dependency 'connection_pool'
spec.add_dependency 'money', '>= 6.6.0'
spec.add_dependency 'redis'
spec.add_dependency 'sorbet'
spec.add_dependency 'sorbet-runtime'

spec.add_development_dependency 'rake', '>= 12.3.3'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'rubocop'
spec.add_development_dependency 'spoom'
spec.add_development_dependency 'tapioca'
spec.add_development_dependency 'timecop'

spec.add_dependency 'connection_pool'
spec.add_dependency 'money', '>= 6.6.0'
spec.add_dependency 'redis'
spec.metadata['rubygems_mfa_required'] = 'true'
end
3 changes: 3 additions & 0 deletions sorbet/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--dir
.
--ignore=vendor/
Empty file added sorbet/rbi/dsl/.keep
Empty file.
Loading
Loading