Skip to content

Commit

Permalink
Merge pull request #16 from Sage/from-hash-arg-error
Browse files Browse the repository at this point in the history
Check the hash given to #from_hash is a hash
  • Loading branch information
ianoxley authored Jul 28, 2023
2 parents b460199 + 752417e commit b223e94
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 79 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Publish Gem
on:
release:
types:
- "created"

jobs:
publish:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Publish to RubyGems
run: |
mkdir -p $HOME/.gem
touch $HOME/.gem/credentials
chmod 0600 $HOME/.gem/credentials
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
gem build hash_kit.gemspec
gem push hash_kit-*.gem
env:
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
26 changes: 26 additions & 0 deletions .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: RSpec
on:
- push

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Run tests
run: |
docker-compose up -d
docker exec gem_test_runner bash -c "cd gem_src && bundle install && bundle exec rspec"
- name: Code Coverage
uses: paambaati/[email protected]
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
with:
debug: true
coverageLocations: |
${{github.workspace}}/coverage/coverage.json:simplecov
prefix: /gem_src
verifyDownload: true
23 changes: 0 additions & 23 deletions .travis.yml

This file was deleted.

7 changes: 7 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
gem_test_runner:
image: ruby:2.7.8-bullseye
container_name: gem_test_runner
command: bash -c "while true; do echo 'Container is running...'; sleep 2; done"
volumes:
- ./:/gem_src
10 changes: 6 additions & 4 deletions hash_kit.gemspec
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'hash_kit/version'
Expand All @@ -13,14 +15,14 @@ Gem::Specification.new do |spec|
spec.homepage = 'https://github.com/sage/hash_kit'
spec.license = 'MIT'

spec.files = Dir.glob("{bin,lib}/**/**/**")
spec.files = Dir.glob('{bin,lib}/**/**/**')
spec.bindir = 'exe'
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']

spec.add_development_dependency 'bundler', '~> 1.11'
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'pry'
spec.add_development_dependency 'rake', '~> 10.0'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'simplecov'
spec.add_development_dependency 'simplecov', '~> 0.21'
end
53 changes: 30 additions & 23 deletions lib/hash_kit/helper.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# frozen_string_literal: true

module HashKit
# Hash kit Helper class
class Helper

#This method is called to make a hash allow indifferent access (it will accept both strings & symbols for a valid key).
# This method is called to make a hash allow indifferent access (it will
# accept both strings & symbols for a valid key).
def indifferent!(hash)
unless hash.is_a?(Hash)
return
end
return unless hash.is_a?(Hash)

#set the default proc to allow the key to be either string or symbol if a matching key is found.
# Set the default proc to allow the key to be either string or symbol if
# a matching key is found.
hash.default_proc = proc do |h, k|
if h.key?(k.to_s)
h[k.to_s]
Expand All @@ -18,9 +20,9 @@ def indifferent!(hash)
end
end

#recursively process any child hashes
# Recursively process any child hashes
hash.each do |key,value|
if hash[key] != nil
unless hash[key].nil?
if hash[key].is_a?(Hash)
indifferent!(hash[key])
elsif hash[key].is_a?(Array)
Expand All @@ -33,9 +35,7 @@ def indifferent!(hash)
end

def indifferent_array!(array)
unless array.is_a?(Array)
return
end
return unless array.is_a?(Array)

array.each do |i|
if i.is_a?(Hash)
Expand All @@ -46,14 +46,16 @@ def indifferent_array!(array)
end
end

#This method is called to convert all the keys of a hash into symbols to allow consistent usage of hashes within your Ruby application.
# This method is called to convert all the keys of a hash into symbols to
# allow consistent usage of hashes within your Ruby application.
def symbolize(hash)
{}.tap do |h|
hash.each { |key, value| h[key.to_sym] = map_value_symbol(value) }
end
end

#This method is called to convert all the keys of a hash into strings to allow consistent usage of hashes within your Ruby application.
# This method is called to convert all the keys of a hash into strings to
# allow consistent usage of hashes within your Ruby application.
def stringify(hash)
{}.tap do |h|
hash.each { |key, value| h[key.to_s] = map_value_string(value) }
Expand All @@ -73,18 +75,22 @@ def to_hash(obj)
hash
end

def from_hash(hash, klass, transforms = [])
# Return an object of type klass from the values in the given hash
#
# @param [Hash] hash
# @param [Class] klass
# @param [Array] transforms
# @return [Object]
def from_hash(hash, klass, transforms = [])
obj = klass.new
if hash ==nil || hash == {}
return obj
end
return obj if hash.nil? || hash.empty?
raise ArgumentError, "#{hash.inspect} is not a hash" unless hash.is_a?(Hash)

hash.each do |k, v|
next unless obj.respond_to?(k)

hash.each do |k,v|
if !obj.respond_to?(k)
next
end
transform = transforms.detect { |t| t.key.to_sym == k.to_sym }
if transform != nil
if !transform.nil?
if v.is_a?(Hash)
child = from_hash(v, transform.klass, transforms)
obj.instance_variable_set("@#{k}", child)
Expand All @@ -98,7 +104,8 @@ def from_hash(hash, klass, transforms = [])
obj.instance_variable_set("@#{k}", v)
end
end
return obj

obj
end

private
Expand Down
6 changes: 0 additions & 6 deletions script/docker-compose.yml

This file was deleted.

53 changes: 30 additions & 23 deletions spec/hash_kit/helper_spec.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe HashKit::Helper do
describe '#symbolize' do

context 'when a single layer hash with string keys is specified' do
let(:hash) { { 'key1' => 'value1', 'key2' => 'value2' } }

Expand Down Expand Up @@ -64,7 +65,6 @@
end

describe '#stringify' do

context 'when a single layer hash with symbol keys is specified' do
let(:hash) { { :key1 => 'value1', :key2 => 'value2' } }

Expand Down Expand Up @@ -122,11 +122,9 @@
expect(new_hash['key3'][1].has_key?(:key4)).to be false
end
end

end

describe '#to_hash' do

let(:key1) do
{ key1: 'value1' }
end
Expand Down Expand Up @@ -195,7 +193,7 @@
end

[
"string" ,
'string' ,
101 ,
1.01 ,
Time.now ,
Expand Down Expand Up @@ -237,36 +235,35 @@
end

describe '#from_hash' do

let(:child_hash) do
{
text: 'abc',
numeric: 5,
time: Time.now,
invalid_key: 5,
bool: true
text: 'abc',
numeric: 5,
time: Time.now,
invalid_key: 5,
bool: true
}
end

let(:parent_hash) do
{
text: 'abc',
numeric: 5,
time: Time.now,
entity: child_hash,
entity_array: [child_hash, child_hash],
invalid_key: 5,
bool: true
text: 'abc',
numeric: 5,
time: Time.now,
entity: child_hash,
entity_array: [child_hash, child_hash],
invalid_key: 5,
bool: true
}
end

let(:string_hash) do
{
'text' => 'abc',
'numeric' => 5,
'time' => Time.now,
'invalid_key' => 5,
'bool' => true
'text' => 'abc',
'numeric' => 5,
'time' => Time.now,
'invalid_key' => 5,
'bool' => true
}
end

Expand Down Expand Up @@ -337,6 +334,12 @@
expect(obj.entity_array[1]).to be_a(TestEntity)
end
end

context 'when hash is not a hash' do
it 'raises an ArgumentError' do
expect { subject.from_hash('Not a hash', TestEntity, transforms) }.to raise_error(ArgumentError)
end
end
end

describe '#indifferent' do
Expand All @@ -356,18 +359,22 @@
}
}
end

it 'should allow access to a string key from a symbol' do
subject.indifferent!(hash)
expect(hash[:key1]).to eq 'value1'
end

it 'should allow access to a symbol key from a string' do
subject.indifferent!(hash)
expect(hash['key2']).to eq 'value2'
end

it 'should allow indifferent access to a key within an array' do
subject.indifferent!(hash)
expect(hash[:key3][0]['key4']).to eq 'value4'
end

it 'should allow indifferent access to a key within an nested hash' do
subject.indifferent!(hash)
expect(hash[:key6]['key7']).to eq 'value7'
Expand Down
6 changes: 6 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# frozen_string_literal: true

require 'simplecov'
require 'simplecov_json_formatter'

SimpleCov.formatter = SimpleCov::Formatter::JSONFormatter

SimpleCov.start do
add_filter 'spec/'
end
Expand Down

0 comments on commit b223e94

Please sign in to comment.