otoindiff 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/README.md +17 -0
- data/Rakefile +8 -0
- data/benchmarks/oto_benchmarks.rb +23 -0
- data/bin/console +11 -0
- data/bin/release +29 -0
- data/bin/setup +8 -0
- data/lib/otoindiff/version.rb +5 -0
- data/lib/otoindiff.rb +78 -0
- data/sig/otoindiff.rbs +31 -0
- metadata +72 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d3ca434647f9c7853413d2a3cd0fd2965b763bfd50c404f583af67a98651b47b
|
4
|
+
data.tar.gz: 9a3bde8b5cbe13efc52f585b77e5bad3a57ab1dc13eae88700a162238c5c986f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2bae63aaa05d12a3bac9e30df8e91f98e3e871fa0d445ccb6804c8f94b5c3c4453eacfbccac675983ac29d71ef4e0a71878eb2a543e105c45e00a5d7f6c1f63
|
7
|
+
data.tar.gz: 983e9a7ccefdff0be3b9ff135a13c1a6df970c0ce1c00c5ea31e4b5a35cda5597e77aad7395ea145b5946ffe571ffcb5c097669eeb2c7e1010874efe10dd7021
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Otoindiff
|
2
|
+
|
3
|
+
`otoindiff` is a Ruby gem that globally enhances the behavior of Ruby's `Hash` class to support **indifferent access** by default. With `otoindiff`, you can access hash keys using either symbols or strings interchangeably without any extra steps like calling `with_indifferent_access`.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- Seamlessly access hash keys as symbols or strings.
|
8
|
+
- Works with nested hashes and supports methods like `dig` and `fetch`.
|
9
|
+
- No need to manually call `with_indifferent_access` on hashes.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'otoindiff'
|
17
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative '../lib/otoindiff'
|
2
|
+
require 'benchmark'
|
3
|
+
|
4
|
+
sample_hash = {
|
5
|
+
foo: 'bar',
|
6
|
+
'baz' => 'qux',
|
7
|
+
'nested' => { 'level1' => { 'level2' => 'value' } }
|
8
|
+
}
|
9
|
+
|
10
|
+
Benchmark.bm do |x|
|
11
|
+
x.report('[] method (symbol key):') { 100_000.times { sample_hash[:foo] } }
|
12
|
+
x.report('[] method (string key):') { 100_000.times { sample_hash['foo'] } }
|
13
|
+
end
|
14
|
+
|
15
|
+
Benchmark.bm do |x|
|
16
|
+
x.report('dig method (nested):') { 100_000.times { sample_hash.dig('nested', 'level1', 'level2') } }
|
17
|
+
x.report('dig method (non-nested):') { 100_000.times { sample_hash.dig(:foo) } }
|
18
|
+
end
|
19
|
+
|
20
|
+
Benchmark.bm do |x|
|
21
|
+
x.report('fetch method (symbol key):') { 100_000.times { sample_hash.fetch(:foo) } }
|
22
|
+
x.report('fetch method (string key):') { 100_000.times { sample_hash.fetch('foo') } }
|
23
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'otoindiff'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require 'irb'
|
11
|
+
IRB.start(__FILE__)
|
data/bin/release
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'bundler/gem_tasks'
|
7
|
+
|
8
|
+
Rake::TestTask.new do |t|
|
9
|
+
t.libs << 'test'
|
10
|
+
t.test_files = FileList['test/**/*_test.rb']
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Run tests and release the gem'
|
15
|
+
task release: [:test] do
|
16
|
+
system('gem build otoindiff.gemspec')
|
17
|
+
|
18
|
+
version = `grep -m1 'version =' otoindiff.gemspec`.split("'")[1]
|
19
|
+
|
20
|
+
if system("gem push otoindiff-#{version}.gem")
|
21
|
+
puts "Successfully released otoindiff version #{version}"
|
22
|
+
system("rm otoindiff-#{version}.gem")
|
23
|
+
else
|
24
|
+
puts 'Failed to push gem'
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
task default: :release
|
data/bin/setup
ADDED
data/lib/otoindiff.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'otoindiff/version'
|
4
|
+
|
5
|
+
require 'active_support'
|
6
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
7
|
+
|
8
|
+
# Extends Ruby's Hash class with more flexible key access methods
|
9
|
+
#
|
10
|
+
# This extension provides enhanced hash key lookup capabilities:
|
11
|
+
# - Allows interchangeable use of string and symbol keys
|
12
|
+
# - Provides more forgiving key access methods
|
13
|
+
# - Maintains original Hash behavior while adding convenience
|
14
|
+
#
|
15
|
+
# @example Flexible key access
|
16
|
+
# hash = { foo: 'bar', 'baz' => 'qux' }
|
17
|
+
# hash[:foo] # => 'bar'
|
18
|
+
# hash['foo'] # => 'bar'
|
19
|
+
# hash.dig('baz', :key) # Nested key access with mixed key types
|
20
|
+
#
|
21
|
+
# @note This extension is designed to be non-intrusive and backwards compatible
|
22
|
+
class Hash
|
23
|
+
alias original_brackets []
|
24
|
+
alias original_dig dig
|
25
|
+
alias original_fetch fetch
|
26
|
+
|
27
|
+
# Retrieve a hash value with flexible key type conversion
|
28
|
+
#
|
29
|
+
# @param key [Object] The key to retrieve
|
30
|
+
# @return [Object, nil] The value associated with the key, or nil if not found
|
31
|
+
def [](key)
|
32
|
+
return original_brackets(key) if key?(key)
|
33
|
+
|
34
|
+
if key.is_a?(String) || key.is_a?(Symbol)
|
35
|
+
original_brackets(key.to_s) || original_brackets(key.to_sym)
|
36
|
+
else
|
37
|
+
original_brackets(key)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Dig into a nested hash with flexible key type conversion
|
42
|
+
#
|
43
|
+
# @param keys [Array<Object>] Path of keys to traverse
|
44
|
+
# @return [Object, nil] The nested value, or nil if path is invalid
|
45
|
+
def dig(*keys)
|
46
|
+
keys.reduce(self) do |current, key|
|
47
|
+
break nil unless current.is_a?(Hash)
|
48
|
+
|
49
|
+
if key.is_a?(String) || key.is_a?(Symbol)
|
50
|
+
current.original_brackets(key) ||
|
51
|
+
current.original_brackets(key.to_s) ||
|
52
|
+
current.original_brackets(key.to_sym)
|
53
|
+
else
|
54
|
+
current.original_brackets(key)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Fetch a hash value with flexible key type conversion and error handling
|
60
|
+
#
|
61
|
+
# @param key [Object] The key to retrieve
|
62
|
+
# @param args [Array] Optional default value or block
|
63
|
+
# @return [Object] The value associated with the key
|
64
|
+
# @raise [KeyError] If key is not found and no default is provided
|
65
|
+
def fetch(key, *args, &block)
|
66
|
+
return original_fetch(key, *args, &block) if key?(key)
|
67
|
+
|
68
|
+
if key.is_a?(String) || key.is_a?(Symbol)
|
69
|
+
begin
|
70
|
+
original_fetch(key.to_s, *args, &block)
|
71
|
+
rescue KeyError
|
72
|
+
original_fetch(key.to_sym, *args, &block)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
original_fetch(key, *args, &block)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/sig/otoindiff.rbs
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Otoindiff
|
2
|
+
VERSION: String
|
3
|
+
|
4
|
+
# Extended methods for Hash class with flexible key access
|
5
|
+
module HashExtensions
|
6
|
+
# Retrieve a value with flexible key type conversion
|
7
|
+
#
|
8
|
+
# @param key [String | Symbol | Object] The key to retrieve
|
9
|
+
# @return [Object?] The value associated with the key, or nil if not found
|
10
|
+
def [](key: String | Symbol | Object): Object?
|
11
|
+
|
12
|
+
# Dig into a nested hash with flexible key type conversion
|
13
|
+
#
|
14
|
+
# @param keys [Array<String | Symbol | Object>] Path of keys to traverse
|
15
|
+
# @return [Object?] The nested value, or nil if path is invalid
|
16
|
+
def dig(*keys: String | Symbol | Object): Object?
|
17
|
+
|
18
|
+
# Fetch a hash value with flexible key type conversion
|
19
|
+
#
|
20
|
+
# @param key [String | Symbol | Object] The key to retrieve
|
21
|
+
# @param default [Object?] Optional default value
|
22
|
+
# @param block [Proc?] Optional block for default value computation
|
23
|
+
# @return [Object] The value associated with the key
|
24
|
+
# @raise [KeyError] If key is not found and no default is provided
|
25
|
+
def fetch(
|
26
|
+
key: String | Symbol | Object,
|
27
|
+
default: Object?,
|
28
|
+
&block: -> Object?
|
29
|
+
): Object
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: otoindiff
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- bugloper
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-12-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '8.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '8.0'
|
27
|
+
description: The otoindiff gem modifies all Ruby Hash objects to support indifferent
|
28
|
+
access by default, allowing seamless use of string or symbol keys interchangeably.
|
29
|
+
email:
|
30
|
+
- bugloper@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- CHANGELOG.md
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- benchmarks/oto_benchmarks.rb
|
39
|
+
- bin/console
|
40
|
+
- bin/release
|
41
|
+
- bin/setup
|
42
|
+
- lib/otoindiff.rb
|
43
|
+
- lib/otoindiff/version.rb
|
44
|
+
- sig/otoindiff.rbs
|
45
|
+
homepage: https://github.com/bugloper/otoindiff
|
46
|
+
licenses: []
|
47
|
+
metadata:
|
48
|
+
allowed_push_host: https://rubygems.org
|
49
|
+
homepage_uri: https://github.com/bugloper/otoindiff
|
50
|
+
source_code_uri: https://github.com/bugloper/otoindiff
|
51
|
+
changelog_uri: https://github.com/bugloper/otoindiff/blob/main/CHANGELOG.md
|
52
|
+
rubygems_mfa_required: 'false'
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.0.0
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubygems_version: 3.5.11
|
69
|
+
signing_key:
|
70
|
+
specification_version: 4
|
71
|
+
summary: Enhances Ruby hashes with default indifferent access.
|
72
|
+
test_files: []
|