Class: BBOpenStruct
- Inherits:
-
Object
show all
- Defined in:
- lib/bb_openstruct.rb
Constant Summary
collapse
- InspectKey =
:__inspect_key__
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(hash = {}) ⇒ BBOpenStruct
Returns a new instance of BBOpenStruct.
9
10
11
12
13
14
15
16
17
18
19
20
|
# File 'lib/bb_openstruct.rb', line 9
def initialize(hash={})
@binding = BBOpenStruct.pure_binding
hash.each_pair do |k,v|
@binding.local_variable_set(k.to_sym, v)
end
@binding.local_variables.each do |name|
get = ->() { @binding.local_variable_get(name) }
set = ->(new_var) { @binding.local_variable_set(name, new_var) }
define_singleton_method(name, get)
define_singleton_method("#{name}=".to_sym, set)
end
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, arg = nil) ⇒ Object
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
# File 'lib/bb_openstruct.rb', line 49
def method_missing(name, arg=nil)
name = name.to_sym
if @binding.local_variables.include?(name)
@binding.local_variable_get(name)
elsif name.to_s[-1] == '=' && frozen?
raise RuntimeError.new "can't modify frozen object"
elsif name.to_s[-1] == '='
pure_name = name.to_s.delete('=').to_sym
@binding.local_variable_set(pure_name, arg)
unless methods.include?(pure_name)
set = ->(new_var) { @binding.local_variable_set(pure_name, new_var) }
get = ->() { @binding.local_variable_get(pure_name) }
define_singleton_method(name, set)
define_singleton_method(pure_name, get)
end
else
err = NoMethodError.new "undefined method `#{name}' for #{self}", name, [arg]
err.set_backtrace caller(1)
raise err
end
end
|
Class Method Details
.pure_binding ⇒ Object
22
23
24
|
# File 'lib/bb_openstruct.rb', line 22
def self.pure_binding
binding
end
|
Instance Method Details
#==(other) ⇒ Object
133
134
135
136
|
# File 'lib/bb_openstruct.rb', line 133
def ==(other)
return false unless other.kind_of?(BBOpenStruct)
to_h == other.to_h
end
|
#[](name) ⇒ Object
71
72
73
|
# File 'lib/bb_openstruct.rb', line 71
def [](name)
method_missing(name)
end
|
#[]=(name, val) ⇒ Object
75
76
77
|
# File 'lib/bb_openstruct.rb', line 75
def []=(name, val)
method_missing("#{name.to_sym}=", val)
end
|
#delete_field(name) ⇒ Object
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
# File 'lib/bb_openstruct.rb', line 26
def delete_field(name)
name = name.to_sym
binding_old = @binding.dup
@binding = BBOpenStruct.pure_binding
binding_old.local_variables.each do |var|
next if var == name
@binding.local_variable_set(var, binding_old.local_variable_get(var))
end
instance_eval("undef #{name}=")
instance_eval("undef #{name}")
binding_old.local_variable_get(name)
end
|
#dig(name, *names) ⇒ Object
Retrieves the value object corresponding to the each name
objects repeatedly.
address = BBOpenStruct.new('city' => "Anytown NC", 'zip' => 12345)
person = BBOpenStruct.new('name' => 'John Smith', 'address' => address)
person.dig(:address, 'zip') person.dig(:business_address, 'zip')
158
159
160
161
162
163
164
165
|
# File 'lib/bb_openstruct.rb', line 158
def dig(name, *names)
begin
name = name.to_sym
rescue NoMethodError
raise TypeError, "#{name} is not a symbol nor a string"
end
to_h.dig(name, *names)
end
|
#each_pair ⇒ Object
115
116
117
118
119
120
121
122
|
# File 'lib/bb_openstruct.rb', line 115
def each_pair
table = {}
@binding.local_variables.each do |k|
table[k] = @binding.local_variable_get(k)
end
return to_enum(__method__) { table.size } unless block_given?
table.each_pair{|p| yield p}
end
|
#eql?(other) ⇒ Boolean
138
139
140
141
|
# File 'lib/bb_openstruct.rb', line 138
def eql?(other)
return false unless other.kind_of?(BBOpenStruct)
to_h.eql?(other.to_h)
end
|
#freeze ⇒ Object
41
42
43
44
45
46
47
|
# File 'lib/bb_openstruct.rb', line 41
def freeze
singleton_methods.each do |method|
instance_eval("undef #{method}") if method.to_s[-1] == '='
end
eval("def self.frozen?; true end")
super
end
|
#hash ⇒ Object
Compute a hash-code for this OpenStruct. Two hashes with the same content will have the same hash code (and will be eql?).
146
147
148
|
# File 'lib/bb_openstruct.rb', line 146
def hash
to_h.hash
end
|
#inspect ⇒ Object
Also known as:
to_s
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
# File 'lib/bb_openstruct.rb', line 91
def inspect
str = "#<#{self.class}"
ids = (Thread.current[InspectKey] ||= [])
if ids.include?(object_id)
return str << ' ...>'
end
ids << object_id
begin
first = true
@binding.local_variables.sort.each do |k|
v = @binding.local_variable_get(k)
str << "," unless first
first = false
str << " #{k}=#{v.inspect}"
end
return str << '>'
ensure
ids.pop
end
end
|
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
79
80
81
82
83
84
85
86
87
88
|
# File 'lib/bb_openstruct.rb', line 79
def respond_to_missing?(method_name, include_private = false)
last_char_name = method_name.to_s[-1]
if last_char_name == '=' && frozen?
false
elsif last_char_name == '=' && @binding.local_variable_defined?(method_name.to_s.tr('=', ''))
true
else
(@binding.local_variables.include?(method_name) && !@binding.local_variable_get(method_name)) || super
end
end
|
#to_h ⇒ Object
124
125
126
127
128
129
130
131
|
# File 'lib/bb_openstruct.rb', line 124
def to_h
output = {}
@binding.local_variables.each do |var|
next if var == :hash
output[var] = @binding.local_variable_get(var)
end
output
end
|