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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5a3a8e4229801dbfdbe059575217825508f53cd9
4
- data.tar.gz: 0e3cec51b79e748742755b4d1d64dfefeb9c8653
2
+ SHA256:
3
+ metadata.gz: 4e6b293c17ad768d3896dab4b0efe4a74d2dfd55558debc8126c15ad9be3bcb3
4
+ data.tar.gz: 0f5a82ffc23700aef19c1a4324fba5f2d75d5d2dcc553f70da8150a463b87977
5
5
  SHA512:
6
- metadata.gz: 94e34836c0816f24a00ab83a0c70c89733a34beb5b6036f402a4341e26565c80e49835d9af912b981edebdc731f86de56e90ce8d94ae450bbdb92d403c82f9eb
7
- data.tar.gz: e80f1d6cb38feaa90d2575b1d993727020b11543b764cd0b35a3c5f9c8cfd2855ec81ac7b6e665b8ac445bec96e3ac09983a1464c779caa026074a12feac65e8
6
+ metadata.gz: 398a48194ae2511f88ca7567d2d19f07759cb6e5cffec76c53f7bc5e8678ab0048dba3f16824671b26b74102aaa806d55af8eddee7a1fed4fe3f3fc587a4ac1f
7
+ data.tar.gz: fad6c4adfe5b08f1cdc4a51506b1e69e402758653ab2e7096a0b5ff10ea3f09447f2f148c76fac5c3d02f1f11148cc4b0c304a13fff4a16352176c5c099a54df
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  .rspec_status
13
13
  .DS_Store
14
14
  .byebug_history
15
+ coverage
@@ -1,11 +1,15 @@
1
- require: rubocop-rspec
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: 15
10
+ Max: 20
11
+ Metrics/ClassLength:
12
+ Max: 110
9
13
  Metrics/BlockLength:
10
14
  Exclude:
11
15
  - 'spec/**/*.rb'
@@ -1,5 +1,5 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.4.1
4
+ - 2.7.1
5
5
  before_install: gem install bundler -v 1.14.6
@@ -1,7 +1,9 @@
1
- require 'meander/version'
2
- require 'meander/common_methods'
3
- require 'meander/plain'
4
- require 'meander/mutable'
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.instance_eval do
12
- def cover_class=(val)
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 define_getter(method)
25
- define_singleton_method method do |&b|
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
@@ -1,7 +1,8 @@
1
- require 'meander/plain'
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 only one up to date object reference
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 # => 2 # Attention! Value remains unchanged
41
- class Mutable < Delegator
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(obj = {})
53
- super
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
- @delegate_sd_obj
67
+ @delegate
68
+ end
69
+
70
+ def __setobj__(*args)
71
+ @delegate = []
72
+ @delegate += args
73
+ @delegate
60
74
  end
61
75
 
62
- def __setobj__(obj)
63
- @delegate_sd_obj = obj
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(self)
86
+ self.class.new(*__getobj__)
76
87
  end
77
88
 
78
- def each &block
79
- if block_given?
80
- __getobj__.each{ |i| yield i }
81
- @own_keys.each{ |i| yield i }
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
- origin = __getobj__
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 key
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?(method, include_private = false)
109
- @own_keys.respond_to?(method) || delegated_key?(method.to_s) || super
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(method, *args, &block)
113
- if @own_keys.respond_to?(method) || block_given?
114
- @own_keys.send method, *args, &block
115
- elsif delegated_key? method
116
- define_getter method
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, :[]=, :is_a?
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
- __getobj__.keys.map(&:to_s).include? key.to_s
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
- delegated = __getobj__
134
- if key.respond_to?(:to_s) && delegated.key?(key.to_s)
135
- delegated[key.to_s]
136
- elsif key.respond_to?(:to_sym) && delegated.key?(key.to_sym)
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
@@ -1,11 +1,13 @@
1
- require 'thor/core_ext/hash_with_indifferent_access'
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 method calling and value block evaluation
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 method evaluation
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(method, *args, &block)
50
- method = method.to_s
51
- if new_key_method? method
52
- key_name = method.gsub(/\=$/, '')
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[method]
57
+ val = self[method_name]
56
58
  val = {} unless self.class.hash_or_cover_class?(val)
57
- send :[]=, method, val
58
- yield(self[method])
59
- elsif key?(method)
60
- define_getter(method)
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?(method, include_private = false)
68
- new_key_method?(method) || key?(method) || super
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Meander
2
- VERSION = '0.1.3'.freeze
4
+ VERSION = '0.2'
3
5
  end
@@ -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', '~> 0.19.4'
34
+ spec.add_runtime_dependency 'thor'
35
35
 
36
- spec.add_development_dependency 'bundler', '~> 1.14'
37
- spec.add_development_dependency 'rake', '~> 10.0'
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.1.3
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: 2017-05-16 00:00:00.000000000 Z
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.4
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.19.4
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: '1.14'
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: '1.14'
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: '10.0'
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: '10.0'
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
- rubyforge_project:
155
- rubygems_version: 2.6.11
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: []