otoindiff 0.1.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/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: []
|