Skip to content
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
13 changes: 9 additions & 4 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
require:
plugins:
- rubocop-rspec

AllCops:
TargetRubyVersion: 3.1
TargetRubyVersion: 3.2
NewCops: enable
Exclude:
- bin/**/*
Expand All @@ -21,13 +21,18 @@ Metrics/BlockLength:
- spec/**/*

Metrics/MethodLength:
CountAsOne: [hash, array, heredoc]
CountAsOne:
- hash
- array
- heredoc

RSpec/AnyInstance:
Enabled: false

RSpec/ExampleLength:
CountAsOne: [hash, array]
CountAsOne:
- hash
- array

RSpec/LeadingSubject:
Enabled: false
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ruby:3.1-alpine
FROM ruby:3.2-alpine

RUN apk add --no-cache --update git build-base

Expand Down
10 changes: 6 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ source "https://rubygems.org"
# Specify your gem's dependencies in scheemer.gemspec
gemspec

gem "rake", "~> 13.0"
gem "rspec", "~> 3.0"
gem "rubocop", "~> 1.21"
gem "rubocop-rspec", "~> 2.12.1"
gem "rake", "~> 13.4"
gem "rspec", "~> 3.13"
gem "rubocop", "~> 1.88"
gem "rubocop-rspec", "~> 3.10"

gem "pry-nav", "~> 1.0"
127 changes: 75 additions & 52 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,88 +1,111 @@
PATH
remote: .
specs:
scheemer (3.0.0)
dry-schema (~> 1.13)
scheemer (3.5.0)
dry-schema (~> 1.16)

GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
concurrent-ruby (1.2.2)
diff-lcs (1.5.0)
dry-configurable (1.0.1)
dry-core (~> 1.0, < 2)
ast (2.4.3)
bigdecimal (4.1.2)
coderay (1.1.3)
concurrent-ruby (1.3.7)
diff-lcs (1.6.2)
dry-configurable (1.3.0)
dry-core (~> 1.1)
zeitwerk (~> 2.6)
dry-core (1.0.0)
dry-core (1.2.0)
concurrent-ruby (~> 1.0)
logger
zeitwerk (~> 2.6)
dry-inflector (1.0.0)
dry-initializer (3.1.1)
dry-logic (1.5.0)
dry-inflector (1.3.1)
dry-initializer (3.2.0)
dry-logic (1.6.0)
bigdecimal
concurrent-ruby (~> 1.0)
dry-core (~> 1.0, < 2)
dry-core (~> 1.1)
zeitwerk (~> 2.6)
dry-schema (1.13.1)
dry-schema (1.16.0)
concurrent-ruby (~> 1.0)
dry-configurable (~> 1.0, >= 1.0.1)
dry-core (~> 1.0, < 2)
dry-initializer (~> 3.0)
dry-logic (>= 1.4, < 2)
dry-types (>= 1.7, < 2)
dry-core (~> 1.1)
dry-initializer (~> 3.2)
dry-logic (~> 1.6)
dry-types (~> 1.9, >= 1.9.1)
zeitwerk (~> 2.6)
dry-types (1.7.1)
dry-types (1.9.1)
bigdecimal (>= 3.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0)
dry-inflector (~> 1.0)
dry-logic (~> 1.4)
zeitwerk (~> 2.6)
json (2.6.3)
parallel (1.23.0)
parser (3.2.2.1)
json (2.19.9)
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
logger (1.7.0)
method_source (1.1.0)
parallel (1.28.0)
parser (3.3.11.1)
ast (~> 2.4.1)
racc
prism (1.9.0)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-nav (1.0.0)
pry (>= 0.9.10, < 0.15)
racc (1.8.1)
rainbow (3.1.1)
rake (13.0.6)
regexp_parser (2.8.0)
rexml (3.2.5)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
rspec-mocks (~> 3.12.0)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.3)
rake (13.4.2)
regexp_parser (2.12.0)
rspec (3.13.2)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.6)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.5)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.8)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.0)
rubocop (1.51.0)
rspec-support (~> 3.13.0)
rspec-support (3.13.7)
rubocop (1.88.0)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.2.0.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (>= 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.28.1)
parser (>= 3.2.1.0)
rubocop-rspec (2.12.1)
rubocop (~> 1.31)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.49.1)
parser (>= 3.3.7.2)
prism (~> 1.7)
rubocop-rspec (3.10.2)
lint_roller (~> 1.1)
regexp_parser (>= 2.0)
rubocop (~> 1.86, >= 1.86.2)
ruby-progressbar (1.13.0)
unicode-display_width (2.4.2)
zeitwerk (2.6.8)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)
zeitwerk (2.8.2)

PLATFORMS
x86_64-linux-musl

DEPENDENCIES
rake (~> 13.0)
rspec (~> 3.0)
rubocop (~> 1.21)
rubocop-rspec (~> 2.12.1)
pry-nav (~> 1.0)
rake (~> 13.4)
rspec (~> 3.13)
rubocop (~> 1.88)
rubocop-rspec (~> 3.10)
scheemer!

BUNDLED WITH
Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "3"
services:
scheemer:
image: "scheemer:latest"
Expand Down
2 changes: 1 addition & 1 deletion lib/scheemer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def initialize(params, data = {})

root_node = permitted.to_h.values.first

super root_node, data.to_h
super(root_node, data.to_h)
end
end
end
Expand Down
12 changes: 11 additions & 1 deletion lib/scheemer/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ def message
end

class InvalidSchemaError < Error
def initialize(result)
super

@result = result
end

def message
"#{title}: #{super}"
"#{title}: #{violations}"
end

def violations
@result.errors.to_h
end

private
Expand Down
18 changes: 9 additions & 9 deletions lib/scheemer/extensions/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,30 @@ module CaseModifier
[first, rest.collect(&:capitalize)].join
end
UNDERSCORER = lambda do |value|
value.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
value.gsub("::", "/")
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
.tr("-", "_")
.downcase
end

refine Symbol do
def camelcase
CAMELCASER.(self).to_sym
CAMELCASER.call(self).to_sym
end

def underscore
UNDERSCORER.(self).to_sym
UNDERSCORER.call(to_s).to_sym
end
end

refine String do
def camelcase
CAMELCASER.(self)
CAMELCASER.call(self)
end

def underscore
UNDERSCORER.(self)
UNDERSCORER.call(self)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/scheemer/fallbacker.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

require_relative "./extensions/hash"
require_relative "extensions/hash"

module Scheemer
module Fallbacker
extend self

using Extensions::Bury

def apply(params, fallbacks)
def apply(params, fallbacks) # rubocop:todo Metrics/MethodLength
cloned_params = params.dup

fallbacks.each do |(path, value)|
Expand Down
34 changes: 28 additions & 6 deletions lib/scheemer/params.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# frozen_string_literal: true

require_relative "./fallbacker"
require_relative "fallbacker"

require_relative "./extensions/string"
require_relative "extensions/string"

module Scheemer
# This handles the conversion from the HTTP linguo (camelCase)
Expand All @@ -27,6 +27,8 @@ def params_fallbacks
end

module InstanceMethods
include Enumerable

def initialize(params, data = {})
@params = Fallbacker.apply(params, self.class.params_fallbacks)

Expand All @@ -37,16 +39,36 @@ def to_h
@params.to_h.transform_keys { |key| key.to_s.underscore }
end

def each(&)
return enum_for(:each) unless block_given?

@params.each(&)
end

def multi_slice(key)
return unless @params.is_a?(Hash)

slices = [
lambda(&:underscore),
lambda(&:camelcase),
->(name) { name },
].map { |a| @params.slice(a.call(key)) }
.reject(&:empty?)

return if slices.empty?

slices.first
end

def method_missing(name, *args, &)
key_name = name.to_sym.camelcase
return @params.fetch(key_name) if @params.key?(key_name)
slice = multi_slice(name.to_sym)
return slice.values.first if slice&.any?

super
end

def respond_to_missing?(name, include_private = false)
key_name = name.camelcase
@params.key?(key_name) || super
multi_slice(name.to_sym)&.any? || super
end
end
end
Expand Down
Loading