gorillib 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.textile +6 -0
- data/README.textile +34 -11
- data/VERSION +1 -1
- data/gorillib.gemspec +63 -5
- data/lib/gorillib/enumerable/sum.rb +2 -2
- data/lib/gorillib/hash/compact.rb +2 -29
- data/lib/gorillib/hash/deep_compact.rb +2 -12
- data/lib/gorillib/hash/deep_dup.rb +4 -0
- data/lib/gorillib/hash/deep_merge.rb +2 -14
- data/lib/gorillib/hash/indifferent_access.rb +207 -0
- data/lib/gorillib/hash/keys.rb +2 -40
- data/lib/gorillib/hash/reverse_merge.rb +2 -24
- data/lib/gorillib/hash/slice.rb +2 -51
- data/lib/gorillib/hash/tree_merge.rb +4 -0
- data/lib/gorillib/hashlike.rb +824 -0
- data/lib/gorillib/hashlike/compact.rb +60 -0
- data/lib/gorillib/hashlike/deep_compact.rb +18 -0
- data/lib/gorillib/hashlike/deep_dup.rb +15 -0
- data/lib/gorillib/hashlike/deep_merge.rb +20 -0
- data/lib/gorillib/hashlike/hashlike_via_accessors.rb +169 -0
- data/lib/gorillib/hashlike/keys.rb +59 -0
- data/lib/gorillib/hashlike/reverse_merge.rb +31 -0
- data/lib/gorillib/hashlike/slice.rb +67 -0
- data/lib/gorillib/hashlike/tree_merge.rb +76 -0
- data/lib/gorillib/metaprogramming/mattr_accessor.rb +1 -1
- data/lib/gorillib/receiver.rb +315 -0
- data/lib/gorillib/receiver/active_model_shim.rb +19 -0
- data/lib/gorillib/receiver/acts_as_hash.rb +191 -0
- data/lib/gorillib/receiver/acts_as_loadable.rb +42 -0
- data/lib/gorillib/receiver/tree_diff.rb +74 -0
- data/lib/gorillib/receiver/validations.rb +30 -0
- data/lib/gorillib/struct/acts_as_hash.rb +108 -0
- data/lib/gorillib/struct/hashlike_iteration.rb +0 -0
- data/notes/fancy_hashes_and_receivers.textile +120 -0
- data/notes/hash_rdocs.textile +97 -0
- data/spec/hash/deep_merge_spec.rb +0 -2
- data/spec/hash/indifferent_access_spec.rb +391 -0
- data/spec/hash/slice_spec.rb +35 -12
- data/spec/hashlike/behave_same_as_hash_spec.rb +105 -0
- data/spec/hashlike/hashlike_behavior_spec.rb +824 -0
- data/spec/hashlike/hashlike_via_accessors_fuzzing_spec.rb +37 -0
- data/spec/hashlike/hashlike_via_accessors_spec.rb +262 -0
- data/spec/hashlike_spec.rb +302 -0
- data/spec/metaprogramming/aliasing_spec.rb +3 -0
- data/spec/metaprogramming/cattr_accessor_spec.rb +2 -0
- data/spec/metaprogramming/class_attribute_spec.rb +2 -0
- data/spec/metaprogramming/delegation_spec.rb +2 -0
- data/spec/metaprogramming/mattr_accessor_spec.rb +2 -0
- data/spec/metaprogramming/singleton_class_spec.rb +3 -0
- data/spec/receiver/acts_as_hash_spec.rb +286 -0
- data/spec/receiver_spec.rb +478 -0
- data/spec/spec_helper.rb +11 -6
- data/spec/string/truncate_spec.rb +1 -0
- data/spec/struct/acts_as_hash_fuzz_spec.rb +67 -0
- data/spec/struct/acts_as_hash_spec.rb +426 -0
- data/spec/support/hashlike_fuzzing_helper.rb +127 -0
- data/spec/support/hashlike_helper.rb +75 -0
- data/spec/support/hashlike_struct_helper.rb +37 -0
- data/spec/support/hashlike_via_delegation.rb +30 -0
- data/spec/support/matchers/be_array_eql.rb +12 -0
- data/spec/support/matchers/be_hash_eql.rb +14 -0
- data/spec/support/matchers/enumerate_method.rb +10 -0
- data/spec/support/matchers/evaluate_to_true.rb +5 -0
- metadata +62 -4
@@ -0,0 +1,42 @@
|
|
1
|
+
module Receiver
|
2
|
+
#
|
3
|
+
# adds methods to load and store from json, yaml or magic
|
4
|
+
#
|
5
|
+
# This will require 'json' UNLESS you have already included something (so if
|
6
|
+
# you want to say require 'yajl' then do that first).
|
7
|
+
#
|
8
|
+
module ActsAsLoadable
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def receive_json stream
|
12
|
+
receive(JSON.load(stream))
|
13
|
+
end
|
14
|
+
|
15
|
+
def receive_yaml stream
|
16
|
+
receive(YAML.load(stream))
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# The file is loaded with
|
21
|
+
# * YAML if the filename ends in .yaml or .yml
|
22
|
+
# * JSON otherwise
|
23
|
+
#
|
24
|
+
def receive_from_file filename
|
25
|
+
stream = File.open(filename)
|
26
|
+
(filename =~ /.ya?ml$/) ? receive_yaml(stream) : receive_json(stream)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def merge_from_file! filename
|
31
|
+
other_obj = self.class.receive_from_file(filename)
|
32
|
+
tree_merge! other_obj
|
33
|
+
end
|
34
|
+
|
35
|
+
# put all the things in ClassMethods at class level
|
36
|
+
def self.included base
|
37
|
+
require 'yaml'
|
38
|
+
require 'json' unless defined?(JSON)
|
39
|
+
base.extend ClassMethods
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Receiver
|
2
|
+
def tree_diff(other)
|
3
|
+
diff_hsh = {}
|
4
|
+
other = other.symbolize_keys if other.respond_to?(:symbolize_keys)
|
5
|
+
each do |k, v|
|
6
|
+
case
|
7
|
+
when v.is_a?(Array) && other[k].is_a?(Array)
|
8
|
+
val = v.tree_diff(other[k])
|
9
|
+
diff_hsh[k] = val unless val.blank?
|
10
|
+
when v.respond_to?(:tree_diff) && other[k].respond_to?(:to_hash)
|
11
|
+
val = v.tree_diff(other[k])
|
12
|
+
diff_hsh[k] = val unless val.blank?
|
13
|
+
else
|
14
|
+
diff_hsh[k] = v unless v == other[k]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
other_hsh = other.dup.delete_if{|k, v| has_key?(k) }
|
18
|
+
diff_hsh.merge!(other_hsh)
|
19
|
+
end
|
20
|
+
|
21
|
+
module ActsAsHash
|
22
|
+
def <=>(other)
|
23
|
+
return 1 if other.blank?
|
24
|
+
each_key do |k|
|
25
|
+
if has_key?(k) && other.has_key?(k)
|
26
|
+
cmp = self[k] <=> other[k]
|
27
|
+
return cmp unless cmp == 0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Array
|
36
|
+
def tree_diff(other)
|
37
|
+
arr = dup
|
38
|
+
if other.length > arr.length then arr = arr + ([nil] * (other.length - arr.length)) end
|
39
|
+
diff_ary = arr.zip(other).map do |arr_el, other_el|
|
40
|
+
if arr_el.respond_to?(:tree_diff) && other_el.respond_to?(:to_hash)
|
41
|
+
arr_el.tree_diff(other_el)
|
42
|
+
else
|
43
|
+
(arr_el == other_el) ? nil : [arr_el, other_el]
|
44
|
+
end
|
45
|
+
end.reject(&:blank?)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Hash
|
50
|
+
# Returns a hash that represents the difference between two hashes.
|
51
|
+
#
|
52
|
+
# Examples:
|
53
|
+
#
|
54
|
+
# {1 => 2}.tree_diff(1 => 2) # => {}
|
55
|
+
# {1 => 2}.tree_diff(1 => 3) # => {1 => 2}
|
56
|
+
# {}.tree_diff(1 => 2) # => {1 => 2}
|
57
|
+
# {1 => 2, 3 => 4}.tree_diff(1 => 2) # => {3 => 4}
|
58
|
+
def tree_diff(other)
|
59
|
+
diff_hsh = self.dup
|
60
|
+
each do |k, v|
|
61
|
+
case
|
62
|
+
when v.is_a?(Array) && other[k].is_a?(Array)
|
63
|
+
diff_hsh[k] = v.tree_diff(other[k])
|
64
|
+
diff_hsh.delete(k) if diff_hsh[k].blank?
|
65
|
+
when v.respond_to?(:tree_diff) && other[k].respond_to?(:to_hash)
|
66
|
+
diff_hsh[k] = v.tree_diff(other[k])
|
67
|
+
diff_hsh.delete(k) if diff_hsh[k].blank?
|
68
|
+
else diff_hsh.delete(k) if v == other[k]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
other_hsh = other.dup.delete_if{|k, v| has_key?(k) || has_key?(k.to_s) }
|
72
|
+
diff_hsh.merge!(other_hsh)
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Receiver
|
2
|
+
|
3
|
+
# An array of strings describing any ways this fails validation
|
4
|
+
def validation_errors
|
5
|
+
errors = []
|
6
|
+
if (ma = missing_attrs).present?
|
7
|
+
errors << "Missing values for {#{ma.join(",")}}"
|
8
|
+
end
|
9
|
+
errors
|
10
|
+
end
|
11
|
+
|
12
|
+
# returns a list of required but missing attributes
|
13
|
+
def missing_attrs
|
14
|
+
missing = []
|
15
|
+
self.class.required_rcvrs.each do |name, info|
|
16
|
+
missing << name if (not attr_set?(name))
|
17
|
+
end
|
18
|
+
missing
|
19
|
+
end
|
20
|
+
|
21
|
+
# methods become class-level
|
22
|
+
module ClassMethods
|
23
|
+
|
24
|
+
# class method gives info for all receiver attributes with required => true
|
25
|
+
def required_rcvrs
|
26
|
+
receiver_attrs.select{|name, info| info[:required] }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Gorillib
|
2
|
+
module Struct
|
3
|
+
#
|
4
|
+
# Make a Struct behave mostly like a hash.
|
5
|
+
#
|
6
|
+
# By default, the hashlike methods iterate over the receiver attributes:
|
7
|
+
# instance #keys delegates to self.class.keys which calls
|
8
|
+
# receiver_attr_names. If you want to filter our add to the keys list, you
|
9
|
+
# can just override the class-level keys method (and call super, or not):
|
10
|
+
#
|
11
|
+
# def self.keys
|
12
|
+
# super + [:firstname, :lastname] - [:fullname]
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# in addition to the below, by including Enumerable, this also adds
|
16
|
+
#
|
17
|
+
# :each_cons, :each_entry, :each_slice, :each_with_index, :each_with_object,
|
18
|
+
# :map, :collect, :collect_concat, :entries, :to_a, :flat_map, :inject, :reduce,
|
19
|
+
# :group_by, :chunk, :cycle, :partition, :reverse_each, :slice_before, :drop,
|
20
|
+
# :drop_while, :take, :take_while, :detect, :find, :find_all, :find_index, :grep,
|
21
|
+
# :all?, :any?, :none?, :one?, :first, :count, :zip :max, :max_by, :min, :min_by,
|
22
|
+
# :minmax, :minmax_by, :sort, :sort_by
|
23
|
+
#
|
24
|
+
# As opposed to hash, does *not* define
|
25
|
+
#
|
26
|
+
# default, default=, default_proc, default_proc=, shift, flatten, compare_by_identity
|
27
|
+
# compare_by_identity? rehash
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# StructUsingHashlike = Struct.new(:a, :b, :c, :z) do
|
31
|
+
# include Gorillib::Struct::ActsAsHash
|
32
|
+
# include Gorillib::Hashlike
|
33
|
+
# end
|
34
|
+
# foo = StructUsingHashlike.new(1,2,3)
|
35
|
+
# foo.to_hash # => { :a => 1, :b => 2, :c => 3, :z => nil }
|
36
|
+
#
|
37
|
+
module ActsAsHash
|
38
|
+
|
39
|
+
# Hashlike#delete
|
40
|
+
#
|
41
|
+
# Deletes and returns the value from +hsh+ whose key is equal to +key+. If the
|
42
|
+
# optional code block is given and the key is not found, pass in the key and
|
43
|
+
# return the result of +block+.
|
44
|
+
#
|
45
|
+
# In a normal hash, a default value can be set; none is provided here.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
# hsh = { :a => 100, :b => 200 }
|
49
|
+
# hsh.delete(:a) # => 100
|
50
|
+
# hsh.delete(:z) # => nil
|
51
|
+
# hsh.delete(:z){|el| "#{el} not found" } # => "z not found"
|
52
|
+
#
|
53
|
+
# @overload hsh.delete(key) -> val
|
54
|
+
# @param key [Object] key to remove
|
55
|
+
# @return [Object, Nil] the removed object, nil if missing
|
56
|
+
#
|
57
|
+
# @overload hsh.delete(key){|key| block } -> val
|
58
|
+
# @param key [Object] key to remove
|
59
|
+
# @yield [Object] called (with key) if key is missing
|
60
|
+
# @yieldparam key
|
61
|
+
# @return [Object, Nil] the removed object, or if missing, the return value
|
62
|
+
# of the block
|
63
|
+
#
|
64
|
+
def delete(key, &block)
|
65
|
+
if has_key?(key)
|
66
|
+
val = self[key]
|
67
|
+
self[key] = nil
|
68
|
+
self.send(:remove_instance_variable, "@#{key}") if instance_variables.include?("@#{key}")
|
69
|
+
val
|
70
|
+
elsif block_given?
|
71
|
+
block.call(key)
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Hashlike#keys
|
78
|
+
#
|
79
|
+
# Returns a new array populated with the keys from this hashlike.
|
80
|
+
#
|
81
|
+
# @see Hashlike#values.
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# hsh = { :a => 100, :b => 200, :c => 300, :d => 400 }
|
85
|
+
# hsh.keys # => [:a, :b, :c, :d]
|
86
|
+
#
|
87
|
+
# @return [Array] list of keys
|
88
|
+
#
|
89
|
+
def keys
|
90
|
+
@keys ||= members.map{|key| convert_key(key) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def empty?
|
94
|
+
keys.select{|key| not self[key].nil? }.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
def convert_key(key)
|
98
|
+
return key if key.is_a?(Fixnum)
|
99
|
+
key.respond_to?(:to_sym) ? key.to_sym : key
|
100
|
+
end
|
101
|
+
|
102
|
+
def size
|
103
|
+
length
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
File without changes
|
@@ -0,0 +1,120 @@
|
|
1
|
+
|
2
|
+
* gorillib/hashlike
|
3
|
+
* gorillib/hashlike/slice
|
4
|
+
* gorillib/hashlike/deep_dup
|
5
|
+
* gorillib/hashlike/
|
6
|
+
* gorillib/hashlike/hashlike_via_accessors
|
7
|
+
* gorillib/struct/acts_as_hash
|
8
|
+
* gorillib/struct/iterates_as_hash
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
h4. acts_as_hash
|
13
|
+
|
14
|
+
* []= associates key with value
|
15
|
+
* [] retrieves value associated with given key
|
16
|
+
* delete removes that key and its association
|
17
|
+
* keys enumeration of all keys having associations.
|
18
|
+
|
19
|
+
|
20
|
+
* check for compatibility/semantics of Enumerable
|
21
|
+
* has_key? true if an association exists for the given key.
|
22
|
+
|
23
|
+
h4. hashlike
|
24
|
+
|
25
|
+
Want chokepoints:
|
26
|
+
|
27
|
+
keys
|
28
|
+
- each, each_pair
|
29
|
+
- each_value
|
30
|
+
- reject!
|
31
|
+
- delete_if
|
32
|
+
- reject
|
33
|
+
- select!
|
34
|
+
- keep_if
|
35
|
+
- each_key
|
36
|
+
- key
|
37
|
+
- has_key?
|
38
|
+
- values_at
|
39
|
+
- length, size
|
40
|
+
- empty?
|
41
|
+
|
42
|
+
|
43
|
+
* each keys.each{|k| yield [k, self[k]] } ; self
|
44
|
+
|
45
|
+
* has_key? keys.include?(k)
|
46
|
+
* length keys.length
|
47
|
+
* size alias for length
|
48
|
+
* empty? keys.empty?
|
49
|
+
|
50
|
+
* each_pair alias for each
|
51
|
+
* each_key keys.each{|k| yield k }
|
52
|
+
* each_value each{|k,v| yield v }
|
53
|
+
* key keys.find{|k| self[k] == val }
|
54
|
+
* values_at in_keys.each{|k| self[k] if has_key?(k) }
|
55
|
+
* values [].tap{|arr| each{|k,v| arr << v } }
|
56
|
+
* to_hash {}.tap{|hsh| each{|k,v| hsh[k] = v } }
|
57
|
+
|
58
|
+
* has_value? keys.any?{|k| self[k] == val }
|
59
|
+
* value? alias for has_value?
|
60
|
+
* include? alias for has_key?
|
61
|
+
* key? alias for has_key?
|
62
|
+
* member? alias for has_key?
|
63
|
+
|
64
|
+
* update other_hash.each{|k,v| self[k] = (block_given? && has_key?(k) ? yield(k,v,self[k]) : v) }
|
65
|
+
* merge! update
|
66
|
+
* merge dup.merge!
|
67
|
+
|
68
|
+
* reject! chgd = false ; each{|k,v| if yield(k,v) then delete(k); chgd = true ; end } chgd ? self : nil
|
69
|
+
* select! chgd = false ; each{|k,v| if !yield(k,v) then delete(k); chgd = true ; end } chgd ? self : nil
|
70
|
+
* delete_if: reject! ; return self
|
71
|
+
* keep_if: select! ; return self
|
72
|
+
* reject: self.dup.delete_if
|
73
|
+
|
74
|
+
* fetch [] if has_key? else default else yield else raise KeyError
|
75
|
+
* clear each_key{|k| delete(k) }
|
76
|
+
|
77
|
+
* invert to_hash.invert
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
#all?, #any?, #chunk, #collect, #collect_concat, #count, #cycle, #detect,
|
82
|
+
#drop, #drop_while, #each_cons, #each_entry, #each_slice,
|
83
|
+
#each_with_index, #each_with_object, #entries, #find, #find_all,
|
84
|
+
#find_index, #first, #flat_map, #grep, #group_by, #inject, #map, #max,
|
85
|
+
#max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition,
|
86
|
+
#reduce, #reverse_each, #slice_before, #sort, #sort_by, #take,
|
87
|
+
#take_while, #zip
|
88
|
+
|
89
|
+
As opposed to hash, does *not* define
|
90
|
+
|
91
|
+
default, default=, default_proc, default_proc=,
|
92
|
+
replace, rehash, compare_by_identity compare_by_identity?,
|
93
|
+
shift, flatten,
|
94
|
+
|
95
|
+
h4. Configliere::DeepHash -- a magic hash
|
96
|
+
|
97
|
+
- only allows handles as keys (only things that can be turned into symbols are interesting)
|
98
|
+
- indifferent access
|
99
|
+
- deep access, via the dotted hash
|
100
|
+
|
101
|
+
* FancyHash
|
102
|
+
|
103
|
+
* *gorillib/hash/compact* compact, compact!, compact_blank, compact_blank!
|
104
|
+
* *gorrilib/hash/deep_compact* deep_compact, deep_compact!
|
105
|
+
* *gorrilib/hash/deep_merge* deep_merge, deep_merge!
|
106
|
+
* *gorillib/hash/keys* stringify_keys, stringify_keys!, symbolize_keys, symbolize_keys!, assert_valid_keys
|
107
|
+
* *gorillib/hash/reverse_merge* reverse_merge, reverse_merge!
|
108
|
+
* *gorillib/hash/tree_merge* tree_merge, tree_merge!
|
109
|
+
* *gorillib/hash/slice* slice, slice!, extract!
|
110
|
+
* *gorillib/hash/zip* Hash.zip
|
111
|
+
|
112
|
+
* Receiver
|
113
|
+
|
114
|
+
|
115
|
+
===========================================================================
|
116
|
+
===========================================================================
|
117
|
+
|
118
|
+
|
119
|
+
?> [ :store, :delete, :keys, :each, :each_key, :each_value, :has_key?, :include?, :key?, :member?, :has_value?, :value?, :fetch, :length, :empty?, :to_hash, :values, :values_at, :merge, :update, :key, :invert, :reject!, :select!, :delete_if, :keep_if, :reject, :clear, :assoc, :rassoc].each{|m| puts `ri 'Hash##{m}'` }
|
120
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
|
2
|
+
# == Hashlike ==
|
3
|
+
#
|
4
|
+
# == ActsAsHash ==
|
5
|
+
#
|
6
|
+
# Uses accessors and instance variables to provide
|
7
|
+
# * :[key] calls the getter <tt>send(key)</tt>
|
8
|
+
# * :[key]= val calls the setter <tt>send("key=", val)</tt>
|
9
|
+
# * :delete removes the instance variable, calls unset!
|
10
|
+
# * :keys all instance variables
|
11
|
+
#
|
12
|
+
# == Hashlike::Slice ==
|
13
|
+
# == Hashlike::Keys ==
|
14
|
+
# == Hashlike::Compact ==
|
15
|
+
# == Hashlike::DeepCompact ==
|
16
|
+
# == Hashlike::DeepMerge ==
|
17
|
+
# == Hashlike::TreeMerge ==
|
18
|
+
# == Hashlike::ReverseMerge ==
|
19
|
+
# == Hashlike::Zip ==
|
20
|
+
# == Hashlike::DeepKeys ==
|
21
|
+
|
22
|
+
|
23
|
+
# Hashlike#each
|
24
|
+
|
25
|
+
|
26
|
+
# Hashlike#each_key
|
27
|
+
|
28
|
+
|
29
|
+
# Hashlike#each_value
|
30
|
+
|
31
|
+
|
32
|
+
# Hashlike#has_key?
|
33
|
+
|
34
|
+
|
35
|
+
# Hashlike#include?
|
36
|
+
# Hashlike#key?
|
37
|
+
# Hashlike#member?
|
38
|
+
|
39
|
+
# Hashlike#has_value?
|
40
|
+
# Hashlike#value?
|
41
|
+
|
42
|
+
|
43
|
+
# Hashlike#fetch
|
44
|
+
|
45
|
+
|
46
|
+
# Hashlike#length
|
47
|
+
|
48
|
+
|
49
|
+
# Hashlike#empty?
|
50
|
+
|
51
|
+
|
52
|
+
# Hashlike#to_hash
|
53
|
+
|
54
|
+
|
55
|
+
# Hashlike#values
|
56
|
+
|
57
|
+
|
58
|
+
# Hashlike#values_at
|
59
|
+
|
60
|
+
|
61
|
+
# Hashlike#key
|
62
|
+
|
63
|
+
|
64
|
+
# Hashlike#invert
|
65
|
+
|
66
|
+
|
67
|
+
# Hashlike#delete_if
|
68
|
+
|
69
|
+
|
70
|
+
# Hashlike#reject!
|
71
|
+
|
72
|
+
|
73
|
+
# Hashlike#reject
|
74
|
+
|
75
|
+
|
76
|
+
# Hashlike#keep_if
|
77
|
+
|
78
|
+
|
79
|
+
# Hashlike#select!
|
80
|
+
|
81
|
+
|
82
|
+
# Hashlike#clear
|
83
|
+
|
84
|
+
|
85
|
+
# Hashlike#assoc
|
86
|
+
|
87
|
+
|
88
|
+
# Hashlike#rassoc
|
89
|
+
|
90
|
+
|
91
|
+
# Hashlike#flatten
|
92
|
+
|
93
|
+
|
94
|
+
# Hashlike#update
|
95
|
+
|
96
|
+
|
97
|
+
# Hashlike#merge
|