meander 0.1.3 → 0.2
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 +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +6 -2
- data/.travis.yml +1 -1
- data/lib/meander.rb +6 -4
- data/lib/meander/common_methods.rb +6 -20
- data/lib/meander/mutable.rb +79 -46
- data/lib/meander/plain.rb +16 -15
- data/lib/meander/version.rb +3 -1
- data/meander.gemspec +5 -3
- metadata +46 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4e6b293c17ad768d3896dab4b0efe4a74d2dfd55558debc8126c15ad9be3bcb3
|
4
|
+
data.tar.gz: 0f5a82ffc23700aef19c1a4324fba5f2d75d5d2dcc553f70da8150a463b87977
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 398a48194ae2511f88ca7567d2d19f07759cb6e5cffec76c53f7bc5e8678ab0048dba3f16824671b26b74102aaa806d55af8eddee7a1fed4fe3f3fc587a4ac1f
|
7
|
+
data.tar.gz: fad6c4adfe5b08f1cdc4a51506b1e69e402758653ab2e7096a0b5ff10ea3f09447f2f148c76fac5c3d02f1f11148cc4b0c304a13fff4a16352176c5c099a54df
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
require:
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
- rubocop-performance
|
2
4
|
AllCops:
|
3
5
|
RSpec:
|
4
6
|
Patterns:
|
5
7
|
- 'spec/meander/.+.rb$'
|
6
8
|
- 'spec/shared/.+.rb$'
|
7
9
|
Metrics/MethodLength:
|
8
|
-
Max:
|
10
|
+
Max: 20
|
11
|
+
Metrics/ClassLength:
|
12
|
+
Max: 110
|
9
13
|
Metrics/BlockLength:
|
10
14
|
Exclude:
|
11
15
|
- 'spec/**/*.rb'
|
data/.travis.yml
CHANGED
data/lib/meander.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'meander/version'
|
4
|
+
require_relative 'meander/common_methods'
|
5
|
+
require_relative 'meander/plain'
|
6
|
+
require_relative 'meander/mutable'
|
5
7
|
|
6
8
|
module Meander # :nodoc:
|
7
9
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Meander
|
2
4
|
module CommonMethods # :nodoc:
|
3
5
|
module ClassMethods # :nodoc:
|
@@ -8,10 +10,8 @@ module Meander
|
|
8
10
|
|
9
11
|
def self.included(base)
|
10
12
|
base.extend ClassMethods
|
11
|
-
base
|
12
|
-
|
13
|
-
@cover_class = val
|
14
|
-
end
|
13
|
+
class << base
|
14
|
+
attr_writer :cover_class
|
15
15
|
|
16
16
|
def cover_class
|
17
17
|
@cover_class ||= self
|
@@ -21,22 +21,8 @@ module Meander
|
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
-
def
|
25
|
-
|
26
|
-
if key?(method)
|
27
|
-
b.call(self[method]) if block_given?
|
28
|
-
self[method]
|
29
|
-
else
|
30
|
-
instance_eval(method) do |name|
|
31
|
-
undef_method name
|
32
|
-
end
|
33
|
-
send method, &block
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def new_key_method?(method)
|
39
|
-
method =~ /^([[:word:]]+)\=$/
|
24
|
+
def new_key_method?(method_name)
|
25
|
+
/=$/.match?(method_name)
|
40
26
|
end
|
41
27
|
end
|
42
28
|
end
|
data/lib/meander/mutable.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'plain'
|
2
4
|
require 'delegate'
|
3
5
|
require 'forwardable'
|
4
|
-
|
5
6
|
module Meander
|
6
7
|
##
|
7
8
|
# This class is a mutable version of Meander::Plain
|
@@ -29,7 +30,7 @@ module Meander
|
|
29
30
|
# a[:a][:b][:c] = 3
|
30
31
|
# m.a.b.c # => 3
|
31
32
|
# ==== Notice
|
32
|
-
# Meander::Mutable support
|
33
|
+
# Meander::Mutable support multiple object references
|
33
34
|
# a = {a: 1}
|
34
35
|
# m = Meander::Mutable.new(a)
|
35
36
|
# b = {b: 2}
|
@@ -37,8 +38,16 @@ module Meander
|
|
37
38
|
# a[:a] = 3
|
38
39
|
# b[:b] = 4
|
39
40
|
# m.a # => 3 # Value is up to date
|
40
|
-
# m.b # =>
|
41
|
-
|
41
|
+
# m.b # => 4 # This value is also up to date
|
42
|
+
# You can also initialize Meander::Mutable with multiple nested hashes
|
43
|
+
# a = {a: 1}
|
44
|
+
# b = {b: 2}
|
45
|
+
# m = Meander::Mutable.new(a, b)
|
46
|
+
# a[:a] = 3
|
47
|
+
# b[:b] = 4
|
48
|
+
# m.a # => 3 # Value is up to date
|
49
|
+
# m.b # => 4 # This value is also up to date
|
50
|
+
class Mutable < ::Thor::CoreExt::HashWithIndifferentAccess
|
42
51
|
include CommonMethods
|
43
52
|
include Enumerable
|
44
53
|
|
@@ -49,46 +58,42 @@ module Meander
|
|
49
58
|
end
|
50
59
|
end
|
51
60
|
|
52
|
-
def initialize(
|
53
|
-
|
54
|
-
@delegate_sd_obj = obj
|
61
|
+
def initialize(required = {}, *args)
|
62
|
+
__setobj__(required, *args)
|
55
63
|
@own_keys = self.class.own_keys_cover_class.new
|
56
64
|
end
|
57
65
|
|
58
66
|
def __getobj__
|
59
|
-
@
|
67
|
+
@delegate
|
68
|
+
end
|
69
|
+
|
70
|
+
def __setobj__(*args)
|
71
|
+
@delegate = []
|
72
|
+
@delegate += args
|
73
|
+
@delegate
|
60
74
|
end
|
61
75
|
|
62
|
-
def
|
63
|
-
@
|
76
|
+
def merge!(hsh)
|
77
|
+
@delegate ||= []
|
78
|
+
@delegate.unshift hsh
|
64
79
|
end
|
65
80
|
|
66
81
|
def key?(key)
|
67
|
-
@own_keys.key?(key) ||
|
68
|
-
begin
|
69
|
-
obj = __getobj__
|
70
|
-
obj.key?(key.to_s) || obj.key?(key.to_sym)
|
71
|
-
end
|
82
|
+
@own_keys.key?(key) || delegated_key?(key)
|
72
83
|
end
|
73
84
|
|
74
85
|
def dup
|
75
|
-
self.class.new(
|
86
|
+
self.class.new(*__getobj__)
|
76
87
|
end
|
77
88
|
|
78
|
-
def each &block
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
else
|
83
|
-
enum_for :each
|
84
|
-
end
|
89
|
+
def each(*args, &block)
|
90
|
+
return enum_for(:each) unless block_given?
|
91
|
+
|
92
|
+
deep_call.each { |i| i.each(*args, &block) }
|
85
93
|
end
|
86
94
|
|
87
95
|
def keys
|
88
|
-
|
89
|
-
own = @own_keys
|
90
|
-
[(origin && origin.keys), (own && own.keys)].flatten
|
91
|
-
.compact.map(&:to_s).uniq
|
96
|
+
map { |k, _| convert_key(k) }
|
92
97
|
end
|
93
98
|
|
94
99
|
def [](key)
|
@@ -96,7 +101,7 @@ module Meander
|
|
96
101
|
if @own_keys.key? key
|
97
102
|
val = @own_keys[key]
|
98
103
|
else
|
99
|
-
val = get_delegated_value
|
104
|
+
val = get_delegated_value(key)
|
100
105
|
if val.is_a?(Hash)
|
101
106
|
val = self.class.new(val)
|
102
107
|
self[key] = val
|
@@ -105,39 +110,67 @@ module Meander
|
|
105
110
|
val
|
106
111
|
end
|
107
112
|
|
108
|
-
def respond_to_missing?(
|
109
|
-
@own_keys.respond_to?(
|
113
|
+
def respond_to_missing?(method_name, include_private = false)
|
114
|
+
@own_keys.respond_to?(method_name) || delegated_key?(method_name) || super
|
110
115
|
end
|
111
116
|
|
112
|
-
def method_missing(
|
113
|
-
if @own_keys.respond_to?(
|
114
|
-
@own_keys.send
|
115
|
-
elsif delegated_key?
|
116
|
-
|
117
|
-
send method, *args, &block
|
117
|
+
def method_missing(method_name, *args, &block)
|
118
|
+
if @own_keys.respond_to?(method_name) || block_given?
|
119
|
+
@own_keys.send method_name, *args, &block
|
120
|
+
elsif delegated_key?(method_name)
|
121
|
+
self[method_name]
|
118
122
|
else
|
119
123
|
super
|
120
124
|
end
|
121
125
|
end
|
122
126
|
|
127
|
+
def kind_of?(klass)
|
128
|
+
(self.class.cover_class == klass) || __getobj__.all?(klass)
|
129
|
+
end
|
130
|
+
|
131
|
+
alias is_a? kind_of?
|
132
|
+
|
123
133
|
extend Forwardable
|
124
|
-
def_delegators :@own_keys, :[]
|
134
|
+
def_delegators :@own_keys, :[]=
|
125
135
|
|
126
136
|
private
|
127
137
|
|
138
|
+
def deep_call(origin: self)
|
139
|
+
stack = []
|
140
|
+
if origin.is_a?(Array)
|
141
|
+
stack.unshift(*origin)
|
142
|
+
origin = stack.pop
|
143
|
+
end
|
144
|
+
Enumerator.new do |yielder|
|
145
|
+
while origin
|
146
|
+
own_keys = origin.instance_variable_get(:@own_keys)
|
147
|
+
if own_keys
|
148
|
+
yielder.yield own_keys
|
149
|
+
stack.unshift(*origin.__getobj__)
|
150
|
+
origin = stack.pop
|
151
|
+
else
|
152
|
+
yielder.yield origin
|
153
|
+
origin = stack.empty? ? nil : stack.pop
|
154
|
+
end
|
155
|
+
end
|
156
|
+
self
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
128
160
|
def delegated_key?(key)
|
129
|
-
|
161
|
+
key = convert_key(key)
|
162
|
+
deep_call(origin: __getobj__).any? do |i|
|
163
|
+
i.keys.any? { |k| convert_key(k) == key }
|
164
|
+
end
|
130
165
|
end
|
131
166
|
|
132
167
|
def get_delegated_value(key)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
delegated[key.to_sym]
|
138
|
-
else
|
139
|
-
delegated[key]
|
168
|
+
value = nil
|
169
|
+
key = convert_key(key)
|
170
|
+
deep_call(origin: __getobj__).detect do |i|
|
171
|
+
i.keys.any? { |k| convert_key(k) == key && value = i[k] }
|
140
172
|
end
|
173
|
+
value
|
141
174
|
end
|
142
175
|
end
|
143
176
|
end
|
data/lib/meander/plain.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'thor/core_ext/hash_with_indifferent_access'
|
4
|
+
require_relative 'common_methods'
|
3
5
|
module Meander
|
4
6
|
##
|
5
7
|
# == Brief
|
6
8
|
# This class is a sugar filled version of HashWithIndifferentAccess
|
7
9
|
#
|
8
|
-
# It supports key-based
|
10
|
+
# It supports key-based method_name calling and value block evaluation
|
9
11
|
# == Configuration
|
10
12
|
# You can set class that will be applied to newly assigned values
|
11
13
|
# require 'active_support/core_ext/hash'
|
@@ -17,7 +19,7 @@ module Meander
|
|
17
19
|
# m[:a] = {}
|
18
20
|
# m[:a].class # => ActiveSupport::HashWithIndifferentAccess
|
19
21
|
# == Usage
|
20
|
-
# === Key based
|
22
|
+
# === Key based method_name evaluation
|
21
23
|
# m = Meander::Plain.new({:a => 1})
|
22
24
|
# m.a # => 1
|
23
25
|
# === New value assignment
|
@@ -46,26 +48,25 @@ module Meander
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
def method_missing(
|
50
|
-
|
51
|
-
if new_key_method?
|
52
|
-
key_name =
|
51
|
+
def method_missing(method_name, *args, &block)
|
52
|
+
method_name = method_name.to_s
|
53
|
+
if new_key_method? method_name
|
54
|
+
key_name = method_name.gsub(/=$/, '')
|
53
55
|
send :[]=, key_name, *args, &block
|
54
56
|
elsif block_given?
|
55
|
-
val = self[
|
57
|
+
val = self[method_name]
|
56
58
|
val = {} unless self.class.hash_or_cover_class?(val)
|
57
|
-
send :[]=,
|
58
|
-
yield(self[
|
59
|
-
elsif key?(
|
60
|
-
|
61
|
-
send method, &block
|
59
|
+
send :[]=, method_name, val
|
60
|
+
yield(self[method_name])
|
61
|
+
elsif key?(method_name)
|
62
|
+
self[method_name]
|
62
63
|
else
|
63
64
|
super
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
67
|
-
def respond_to_missing?(
|
68
|
-
new_key_method?(
|
68
|
+
def respond_to_missing?(method_name, include_private = false)
|
69
|
+
new_key_method?(method_name) || key?(method_name) || super
|
69
70
|
end
|
70
71
|
end
|
71
72
|
end
|
data/lib/meander/version.rb
CHANGED
data/meander.gemspec
CHANGED
@@ -31,12 +31,14 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
32
|
spec.require_paths = ['lib']
|
33
33
|
|
34
|
-
spec.add_runtime_dependency 'thor'
|
34
|
+
spec.add_runtime_dependency 'thor'
|
35
35
|
|
36
|
-
spec.add_development_dependency 'bundler'
|
37
|
-
spec.add_development_dependency
|
36
|
+
spec.add_development_dependency 'bundler'
|
37
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
38
38
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
39
39
|
spec.add_development_dependency 'rubocop'
|
40
40
|
spec.add_development_dependency 'rubocop-rspec'
|
41
|
+
spec.add_development_dependency 'rubocop-performance'
|
41
42
|
spec.add_development_dependency 'hashie'
|
43
|
+
spec.add_development_dependency 'simplecov'
|
42
44
|
end
|
metadata
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: meander
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kostrov Alexander
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 12.3.3
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 12.3.3
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop-performance
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: hashie
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,20 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
description: Hashie clone with a bit more sugar
|
112
140
|
email:
|
113
141
|
- bombazook@gmail.com
|
@@ -136,7 +164,7 @@ licenses:
|
|
136
164
|
- MIT
|
137
165
|
metadata:
|
138
166
|
allowed_push_host: https://rubygems.org
|
139
|
-
post_install_message:
|
167
|
+
post_install_message:
|
140
168
|
rdoc_options: []
|
141
169
|
require_paths:
|
142
170
|
- lib
|
@@ -151,9 +179,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
179
|
- !ruby/object:Gem::Version
|
152
180
|
version: '0'
|
153
181
|
requirements: []
|
154
|
-
|
155
|
-
|
156
|
-
signing_key:
|
182
|
+
rubygems_version: 3.1.4
|
183
|
+
signing_key:
|
157
184
|
specification_version: 4
|
158
185
|
summary: Just another ruby Hash extension
|
159
186
|
test_files: []
|