hash_dial 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +35 -0
- data/README.md +79 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/hash_dial.gemspec +28 -0
- data/lib/hash_dial.rb +20 -0
- data/lib/hash_dial/hash_dialler.rb +61 -0
- data/lib/hash_dial/version.rb +3 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9a2e69ddcb5f84bef6fa164953fa3a127396568cd91ee1debbad926902e29df3
|
4
|
+
data.tar.gz: efa91b61097992c4b3a57545d9cb64af8cd4a9fa924277e2c5f1af60f967e1bb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b776b72153e96ff264e3c859cb1a12b37a06d8baa3538735e34dcffb8331780597ed119cc032c11ccdb70379f45f888ec497b09c417aeab794cc5917c29660ae
|
7
|
+
data.tar.gz: 4c38e006c1140bb59afc72e2fadb347e40887c49e5b7274d59e2b9cef1c33e54fde80ff475944ed9bb541ddc296ccad9a0ff61a6d86b413993e1ef03dded41a9
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
hash_dial (1.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.3)
|
10
|
+
rake (10.5.0)
|
11
|
+
rspec (3.8.0)
|
12
|
+
rspec-core (~> 3.8.0)
|
13
|
+
rspec-expectations (~> 3.8.0)
|
14
|
+
rspec-mocks (~> 3.8.0)
|
15
|
+
rspec-core (3.8.0)
|
16
|
+
rspec-support (~> 3.8.0)
|
17
|
+
rspec-expectations (3.8.2)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.8.0)
|
20
|
+
rspec-mocks (3.8.0)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.8.0)
|
23
|
+
rspec-support (3.8.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
bundler (~> 1.17)
|
30
|
+
hash_dial!
|
31
|
+
rake (~> 10.0)
|
32
|
+
rspec (~> 3.0)
|
33
|
+
|
34
|
+
BUNDLED WITH
|
35
|
+
1.17.2
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# HashDial
|
2
|
+
|
3
|
+
**Avoid all errors when accessing a deeply nested Hash key.** HashDial goes one step beyond Hash::dig() by returning nil (or your default) if the keys requested are invalid for any reason.
|
4
|
+
|
5
|
+
In particular, if you try to access a key on a value that isn't a hash, dig() will cause an error where HashDial will not.
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
hash = {a: {b: {c: true}, d: 5}}
|
9
|
+
hash.dig( :a, :d, :c) #=> TypeError: Integer does not have #dig method
|
10
|
+
hash.call(:a, :d, :c) #=> nil
|
11
|
+
hash.call(:a, :b, :c) #=> true
|
12
|
+
```
|
13
|
+
|
14
|
+
**Bonus: you don't even need to fiddle with existing code.** If you have already written something to access a deep hash key, just surround this with `dial` and `call` (rather than changing it to the form above as function parameters).
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
hash[:a][:d][:c] #=> TypeError: no implicit conversion of Symbol into Integer
|
18
|
+
#hash → [:a][:d][:c]
|
19
|
+
# ↓ ↓
|
20
|
+
hash.dial[:a][:d][:c].call #=> nil
|
21
|
+
```
|
22
|
+
|
23
|
+
## Explanation
|
24
|
+
|
25
|
+
We use the concept of placing a phone-call: you can 'dial' any set of keys regardless of whether they exist (like entering a phone number), then finally place the 'call'. If the key is invalid for any reason you get nil/default (like a wrong number); otherwise you get the value (you're connected).
|
26
|
+
|
27
|
+
This works by intermediating your request with a HashDialler object. Trying to access keys on this object simply builds up a list of keys to use when you later place the 'call'.
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
gem 'hash_dial'
|
35
|
+
```
|
36
|
+
|
37
|
+
And then execute:
|
38
|
+
|
39
|
+
$ bundle
|
40
|
+
|
41
|
+
Or install it yourself as:
|
42
|
+
|
43
|
+
$ gem install hash_dial
|
44
|
+
|
45
|
+
## Usage
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'hash_dial'
|
49
|
+
```
|
50
|
+
|
51
|
+
### Use it like dig()
|
52
|
+
|
53
|
+
If you want to follow this pattern, it works in the same way. You can't change the default return value when using this pattern.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
hash.call(:a, :b, :c) #=> Returns the value at hash[:a][:b][:c] or nil
|
57
|
+
```
|
58
|
+
|
59
|
+
### Use it like a Hash -- allows default return value
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
hash.dial[:a][:b][:c].call #=> Returns the value at hash[:a][:b][:c] or nil
|
63
|
+
hash.dial[:a][:b][:c].call('Ooops') #=> Returns the value at hash[:a][:b][:c] or 'Ooops'
|
64
|
+
```
|
65
|
+
|
66
|
+
If you don't do this all in one line, you can access the HashDialler object should you want to manipulate it:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
dialler = hash.dial # Returns a HashDialler object referencing hash
|
70
|
+
dialler[:a] # Adds :a to the list of keys to dial (returns self)
|
71
|
+
dialler.dial!(:b, :c) # Longhand way of adding more keys (returns self)
|
72
|
+
dialler.undial! # Removes the last-added key (returns self)
|
73
|
+
dialler[:c][:d] # Adds two more keys (returns self)
|
74
|
+
dialler += :e # Adds yet one more (returns self)
|
75
|
+
dialler -= :a # Removes all such keys from the list (returns self)
|
76
|
+
# So far we have dialled [:b][:c][:d][:e]
|
77
|
+
dialler.call #=> Returns the value at hash[:b][:c][:d][:e] or nil
|
78
|
+
dialler.hangup #=> Returns the original hash by reference
|
79
|
+
```
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "hash_dial"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/hash_dial.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "hash_dial/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "hash_dial"
|
8
|
+
spec.version = HashDial::VERSION
|
9
|
+
spec.authors = ["Convincible"]
|
10
|
+
spec.email = ["development@convincible.media"]
|
11
|
+
|
12
|
+
spec.summary = "Access (deeply nested) hash keys. Get the value, or nil on any error. (Even safer than Hash::dig)."
|
13
|
+
spec.description = "Avoid all errors when accessing a (deeply nested) Hash key. HashDial goes one step beyond Hash::dig() by returning nil (or your default) if the keys requested are invalid for any reason at all. Bonus: you don't even need to fiddle with existing code. If you have already written something to access a deep hash key, just surround this with '.dial' and '.call'."
|
14
|
+
spec.homepage = "https://github.com/ConvincibleMedia/hash_dial"
|
15
|
+
|
16
|
+
# Specify which files should be added to the gem when it is released.
|
17
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
18
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
19
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
|
+
end
|
21
|
+
spec.bindir = "exe"
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
+
end
|
data/lib/hash_dial.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "hash_dial/version"
|
2
|
+
require "hash_dial/hash_dialler"
|
3
|
+
|
4
|
+
module HashDial
|
5
|
+
|
6
|
+
def to_dial(*lookup)
|
7
|
+
return HashDialler.new(self, *lookup)
|
8
|
+
end
|
9
|
+
|
10
|
+
alias_method :dial, :to_dial
|
11
|
+
|
12
|
+
def call(*lookup)
|
13
|
+
return HashDialler.new(self, *lookup).call
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class Hash
|
19
|
+
include HashDial
|
20
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module HashDial
|
2
|
+
|
3
|
+
class HashDialler
|
4
|
+
|
5
|
+
@hash
|
6
|
+
@lookup
|
7
|
+
@default = nil
|
8
|
+
|
9
|
+
def initialize(hash, *lookup)
|
10
|
+
if hash.is_a?(Hash)
|
11
|
+
@hash = hash
|
12
|
+
else
|
13
|
+
@hash = {}
|
14
|
+
end
|
15
|
+
@lookup = []
|
16
|
+
if lookup.length > 0
|
17
|
+
dial!(*lookup)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def dial!(*keys)
|
22
|
+
#unless key.is_a(Symbol) || key.is_a(String)
|
23
|
+
@lookup += keys
|
24
|
+
return self
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(default = nil)
|
28
|
+
begin
|
29
|
+
value = @hash.dig(*@lookup)
|
30
|
+
rescue
|
31
|
+
value = default
|
32
|
+
end
|
33
|
+
return value
|
34
|
+
end
|
35
|
+
|
36
|
+
def hangup
|
37
|
+
return @hash
|
38
|
+
end
|
39
|
+
|
40
|
+
def undial!(*keys)
|
41
|
+
if keys.length > 0
|
42
|
+
@lookup -= keys
|
43
|
+
elsif @lookup.length > 0
|
44
|
+
@lookup.pop
|
45
|
+
end
|
46
|
+
return self
|
47
|
+
end
|
48
|
+
|
49
|
+
def [](key)
|
50
|
+
return dial!(key)
|
51
|
+
end
|
52
|
+
def +(key)
|
53
|
+
return dial!(key)
|
54
|
+
end
|
55
|
+
def -(key)
|
56
|
+
return undial!(key)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hash_dial
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Convincible
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: 'Avoid all errors when accessing a (deeply nested) Hash key. HashDial
|
56
|
+
goes one step beyond Hash::dig() by returning nil (or your default) if the keys
|
57
|
+
requested are invalid for any reason at all. Bonus: you don''t even need to fiddle
|
58
|
+
with existing code. If you have already written something to access a deep hash
|
59
|
+
key, just surround this with ''.dial'' and ''.call''.'
|
60
|
+
email:
|
61
|
+
- development@convincible.media
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- ".gitignore"
|
67
|
+
- ".rspec"
|
68
|
+
- ".travis.yml"
|
69
|
+
- Gemfile
|
70
|
+
- Gemfile.lock
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- bin/console
|
74
|
+
- bin/setup
|
75
|
+
- hash_dial.gemspec
|
76
|
+
- lib/hash_dial.rb
|
77
|
+
- lib/hash_dial/hash_dialler.rb
|
78
|
+
- lib/hash_dial/version.rb
|
79
|
+
homepage: https://github.com/ConvincibleMedia/hash_dial
|
80
|
+
licenses: []
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubygems_version: 3.0.0
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Access (deeply nested) hash keys. Get the value, or nil on any error. (Even
|
101
|
+
safer than Hash::dig).
|
102
|
+
test_files: []
|