Module: Ryo::Reflect
Overview
The Ryo::Reflect module mirrors
JavaScript's Relfect
object,
and some of the static methods on JavaScript's
Object
as well.
Ryo::Reflect also implements Ryo-specific reflection features. The instance methods of this module are available as singleton methods on the Ryo module.
JavaScript equivalents (Reflect) collapse
-
#define_property(ryo, property, value)
Equivalent to JavaScript's
Reflect.defineProperty
. -
#properties_of(ryo) ⇒ Array<String>
Equivalent to JavaScript's
Reflect.ownKeys
, and JavaScript'sObject.keys
. -
#prototype_of(ryo) ⇒ Ryo?
Equivalent to JavaScript's
Reflect.getPrototypeOf
. -
#set_prototype_of(ryo, prototype) ⇒ nil
Equivalent to JavaScript's
Reflect.setPrototypeOf
.
JavaScript equivalents (Object) collapse
-
#assign(target, *sources) ⇒ Ryo
Equivalent to JavaScript's
Object.assign
. -
#property?(ryo, property) ⇒ Boolean
Equivalent to JavaScript's
Object.hasOwn
, andObject.prototype.hasOwnProperty
.
Ryo-specific collapse
- #call_method(ryo, method, *args, &b) ⇒ ::Object, ::BasicObject
-
#class_of(ryo) ⇒ Class
Returns the class of a Ryo object.
-
#delete!(ryo, property)
The #delete! method deletes a property from a Ryo object, and from the prototypes in its prototype chain.
-
#equal?(ryo1, ryo2) ⇒ Boolean
Returns true when the two Ryo objects are strictly equal.
-
#function?(obj) ⇒ Boolean
Returns true when given a Ryo function.
-
#inspect_object(ryo) ⇒ String
Returns a String representation of a Ryo object.
-
#memo?(obj) ⇒ Boolean
(also: #lazy?)
Returns true when given a Ryo memo.
-
#prototype_chain_of(ryo) ⇒ Array<Ryo::Object, Ryo::BasicObject>
Returns the prototype chain of a Ryo object.
-
#ryo?(obj) ⇒ Boolean
Returns true when given a Ryo object.
-
#set_table_of(ryo, table) ⇒ nil
Sets the table of a Ryo object.
-
#table_of(ryo, recursive: false) ⇒ Hash
Returns the table of a Ryo object.
Instance Method Details
#assign(target, *sources) ⇒ Ryo
Equivalent to JavaScript's Object.assign
.
117 118 119 120 121 122 |
# File 'lib/ryo/reflect.rb', line 117 def assign(target, *sources) sources.each do |source| to_hash(source).each { target[_1.to_s] = _2 } end target end |
#call_method(ryo, method, *args, &b) ⇒ ::Object, ::BasicObject
206 207 208 209 |
# File 'lib/ryo/reflect.rb', line 206 def call_method(ryo, method, *args, &b) kernel(:__send__) .bind_call(ryo, method, *args, &b) end |
#class_of(ryo) ⇒ Class
Returns the class of a Ryo object
216 217 218 |
# File 'lib/ryo/reflect.rb', line 216 def class_of(ryo) kernel(:class).bind_call(ryo) end |
#define_property(ryo, property, value)
This method returns an undefined value.
Equivalent to JavaScript's Reflect.defineProperty
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/ryo/reflect.rb', line 59 def define_property(ryo, property, value) table, property = table_of(ryo), property.to_s kernel(:tap).bind_call(value) { _1.bind!(ryo) if function?(_1) } table[property] = value # Define setter if !setter_defined?(ryo, property) && property[-1] != "?" define_method!(ryo, "#{property}=") { ryo[property] = _1 } end # Define getter return if getter_defined?(ryo, property) define_method!(ryo, property) { |*args, &b| (args.empty? && b.nil?) ? ryo[property] : super(*args, &b) } nil end |
#delete!(ryo, property)
This method returns an undefined value.
The #delete! method deletes a property from a Ryo object, and from the prototypes in its prototype chain
138 139 140 141 142 |
# File 'lib/ryo/reflect.rb', line 138 def delete!(ryo, property) [ryo, *prototype_chain_of(ryo)].each do Ryo.delete(_1, property.to_s) end end |
#equal?(ryo1, ryo2) ⇒ Boolean
Returns true when the two Ryo objects are strictly equal
260 261 262 |
# File 'lib/ryo/reflect.rb', line 260 def equal?(ryo1, ryo2) kernel(:equal?).bind_call(ryo1, ryo2) end |
#function?(obj) ⇒ Boolean
Returns true when given a Ryo function
225 226 227 |
# File 'lib/ryo/reflect.rb', line 225 def function?(obj) Ryo::Function === obj end |
#inspect_object(ryo) ⇒ String
Returns a String representation of a Ryo object
269 270 271 272 273 274 275 276 |
# File 'lib/ryo/reflect.rb', line 269 def inspect_object(ryo) format( "#<Ryo object=%{object} proto=%{proto} table=%{table}>", object: Object.instance_method(:to_s).bind_call(ryo), proto: prototype_of(ryo).inspect, table: table_of(ryo).inspect ) end |
#memo?(obj) ⇒ Boolean Also known as: lazy?
Returns true when given a Ryo memo
234 235 236 |
# File 'lib/ryo/reflect.rb', line 234 def memo?(obj) Ryo::Memo === obj end |
#properties_of(ryo) ⇒ Array<String>
Equivalent to JavaScript's Reflect.ownKeys
, and
JavaScript's Object.keys
84 85 86 |
# File 'lib/ryo/reflect.rb', line 84 def properties_of(ryo) table_of(ryo).keys end |
#property?(ryo, property) ⇒ Boolean
Equivalent to JavaScript's Object.hasOwn
,
and Object.prototype.hasOwnProperty
.
103 104 105 |
# File 'lib/ryo/reflect.rb', line 103 def property?(ryo, property) table_of(ryo).key?(property.to_s) end |
#prototype_chain_of(ryo) ⇒ Array<Ryo::Object, Ryo::BasicObject>
Returns the prototype chain of a Ryo object
149 150 151 152 153 154 155 156 157 |
# File 'lib/ryo/reflect.rb', line 149 def prototype_chain_of(ryo) prototypes = [] loop do ryo = prototype_of(ryo) break unless ryo prototypes.push(ryo) end prototypes end |
#prototype_of(ryo) ⇒ Ryo?
Equivalent to JavaScript's Reflect.getPrototypeOf
28 29 30 31 |
# File 'lib/ryo/reflect.rb', line 28 def prototype_of(ryo) kernel(:instance_variable_get) .bind_call(ryo, :@_proto) end |
#ryo?(obj) ⇒ Boolean
Returns true when given a Ryo object
249 250 251 |
# File 'lib/ryo/reflect.rb', line 249 def ryo?(obj) Ryo === obj end |
#set_prototype_of(ryo, prototype) ⇒ nil
Equivalent to JavaScript's Reflect.setPrototypeOf
43 44 45 46 47 |
# File 'lib/ryo/reflect.rb', line 43 def set_prototype_of(ryo, prototype) kernel(:instance_variable_set) .bind_call(ryo, :@_proto, prototype) nil end |
#set_table_of(ryo, table) ⇒ nil
Sets the table of a Ryo object
190 191 192 193 194 |
# File 'lib/ryo/reflect.rb', line 190 def set_table_of(ryo, table) kernel(:instance_variable_set) .bind_call(ryo, :@_table, table) nil end |
#table_of(ryo, recursive: false) ⇒ Hash
Returns the table of a Ryo object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/ryo/reflect.rb', line 167 def table_of(ryo, recursive: false) table = kernel(:instance_variable_get).bind_call(ryo, :@_table) if recursive table.each do |key, value| if ryo?(value) table[key] = table_of(value, recursive:) elsif value.respond_to?(:each) table[key] = value.respond_to?(:each_pair) ? value : value.map { table_of(_1, recursive:) } end end end table end |