RbObjectAccess
public class RbObjectAccess
Provides services to manipulate a Ruby object:
- Call methods;
- Access properties and instance variables;
- Access class variables;
- Access global variables;
- Find constants, classes, and modules.
The class is abstract. You use it via RbObject
and the global Ruby
instance
of RbGateway
.
By default all methods throw RbError
s if anything goes wrong including
when Ruby raises an exception. Use the RbObjectAccess.failable
adapter to
access an alternative API that returns nil
on errors instead. You can still
see any Ruby exceptions via RbError.history
.
Calling methods
Ruby has a few different ways to call methods that are reflected in the various Swift methods here and their types. The degrees of freedom are:
- Call method by name or by symbol;
- Pass positional and/or keyword arguments;
- Optionally pass a block that can be expressed as a Swift function or a Ruby Proc.
- Method can either raise an exception or return a value.
From the simple:
try! obj.call("myMethod")
…to more baroque:
do {
let result =
try obj.call(symbol: myMethodSymbol,
args: [1, "3.5", myHash],
kwArgs: [("mode", RbSymbol("debug")]) { blockArgs in
blockArgs.forEach {
process($0)
}
return .nilObject
}
} catch RbError.rubyException(let exn) {
handleErrors(error)
} catch {
...
}
When passing a Swift function as a block there are two methods to choose from. If the block is used only within the method execution you can provide a non-escaping, non-sendable function; if the block is persisted and used later then you must provide a retention rule and an escaping, sendable function.
Topics
Instance Variables
func getInstanceVar(String) -> RbObject
func getInstanceVar(String) -> RbObject
Get the value of a Ruby instance variable. Creates a new one with a nil
value
if it doesn’t exist yet.
For a version that does not throw, see failable
.
Declaration
Parameters
name |
Name of IVar to get. Must begin with a single ‘@’. |
Throws
RbError.badIdentifier(type:id:)
if name
looks wrong.
RbError.rubyException(_:)
if Ruby has a problem.
Return Value
Value of the IVar or Ruby nil
if it has not been assigned yet.
func setInstanceVar(String, newValue: (any RbObjectConvertible)?) -> RbObject
func setInstanceVar(String, newValue: (any RbObjectConvertible)?) -> RbObject
Set a Ruby instance variable. Creates a new one if it doesn’t exist yet.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func setInstanceVar(_ name: String, newValue: (any RbObjectConvertible)?)
throws -> RbObject
Parameters
name |
Name of Ivar to set. Must begin with a single ‘@’. |
newValue |
New value to set. |
Throws
RbError.badIdentifier(type:id:)
if name
looks wrong.
RbError.rubyException(_:)
if Ruby has a problem.
Return Value
The value that was set.
Failable Access
var failable: RbFailableAccess
var failable: RbFailableAccess
Get a version of this API that returns nil
instead of throwing errors.
See RbFailableAccess
.
Declaration
public var failable: RbFailableAccess { get }
Constants
func getConstant(String) -> RbObject
func getConstant(String) -> RbObject
Get an RbObject
that represents a Ruby constant.
In Ruby constants include things that users think of as constants like
Math::PI
, classes, and modules. You can use this routine with
any kind of constant, but see getClass(...)
for a little more sugar.
let rubyPi = Ruby.getConstant("Math::PI")
let crumbs = rubyPi - Double.pi
This is a dynamic call into Ruby that can cause calls to const_missing
and autoloading.
For a version that does not throw, see failable
.
Declaration
Parameters
name |
The name of the constant to look up. Can contain ‘::’ sequences to drill down through nested classes and modules. If you call this method on an |
Throws
RbError.rubyException(_:)
if the constant cannot be found.
Return Value
An RbObject
for the constant.
func setConstant(String, newValue: (any RbObjectConvertible)?) -> RbObject
func setConstant(String, newValue: (any RbObjectConvertible)?) -> RbObject
Bind an object to a constant name.
Use this to add value-constants to the class/module name hierarchy. For example:
let defaultInvader = RbObject(ofClass: "Invader", kwArgs: ["name" : "Zaltor"])
try Ruby.setConstant("Game::Invaders::DEFAULT", defaultInvader)
To define new classes and modules, use RbGateway.defineClass(...)
and
RbGateway.defineModule(...)
instead of this method.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func setConstant(_ name: String, newValue: (any RbObjectConvertible)?)
throws -> RbObject
Parameters
name |
The name of the constant to create or replace. Can contain ‘::’ sequences to drill down through nested classes and modules. |
newValue |
The value for the constant. |
Throws
RbError.badIdentifier(type:id:)
if name
looks wrong.
rubyException(_:)
if there is a Ruby exception.
RbError.badType(_:)
if the current object is not a class or module.
Return Value
The value set for the constant.
func getClass(String) -> RbObject
func getClass(String) -> RbObject
Get an RbObject
that represents a Ruby class.
This is a dynamic call into Ruby that can cause calls to const_missing
and autoloading.
One way of creating an instance of a class:
let myClass = try Ruby.getClass("MyModule::MyClass")
let myObj = try myClass.call("new")
Although it is easier to write:
let myObj = try RbObject(ofClass: "MyModule::MyClass")
For a version that does not throw, see failable
.
Declaration
Parameters
name |
The name of the class to look up. Can contain ‘::’ sequences to drill down through nested classes and modules. If you call this method on an |
Throws
RbError.rubyException(_:)
if the constant cannot be found.
RbError.badType(_:)
if the constant is found but is not a class.
Return Value
An RbObject
for the class.
Method Call
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>) -> RbObject
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>) -> RbObject
Call a Ruby object method.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
_ methodName: String,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:]
) throws -> RbObject
Parameters
methodName |
The name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
Return Value
The result of calling the method.
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockCall: RbBlockCallback) -> RbObject
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockCall: RbBlockCallback) -> RbObject
Call a Ruby object method passing Swift code as a block used immediately.
This version is for something like Enumerable#each
where the block is used
only in the context of this method and never again. The Swift closure does not have
to be escaping or sendable.
If the method you’re calling retains the block in some way, associating it with the called
or returned object for future use, then the Swift closure must be both escaping and sendable
and you must call the method with call(_:args:kwArgs:blockRetention:blockCall:)
.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
_ methodName: String,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:],
blockCall: RbBlockCallback
) throws -> RbObject
Parameters
methodName |
The name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
blockCall |
Swift code to pass as a block to the method. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
Return Value
The result of calling the method.
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockRetention: RbBlockRetention, blockCall: RbBlockCallback) -> RbObject
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockRetention: RbBlockRetention, blockCall: RbBlockCallback) -> RbObject
Call a Ruby object method passing Swift code as a block.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
_ methodName: String,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:],
blockRetention: RbBlockRetention,
blockCall: @escaping @Sendable RbBlockCallback
) throws -> RbObject
Parameters
methodName |
The name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
blockRetention |
Should the |
blockCall |
Swift code to pass as a block to the method. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
Return Value
The result of calling the method.
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, block: any RbObjectConvertible) -> RbObject
func call(String, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, block: any RbObjectConvertible) -> RbObject
Call a Ruby object method passing a Ruby Proc as a block.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
_ methodName: String,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:],
block: any RbObjectConvertible
) throws -> RbObject
Parameters
methodName |
The name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
block |
A Ruby proc to pass as a block to the method. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
RbError.badType(_:)
if block
does not convert to a Proc.
Return Value
The result of calling the method.
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>) -> RbObject
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>) -> RbObject
Call a Ruby object method using a symbol.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
symbol: any RbObjectConvertible,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:]
) throws -> RbObject
Parameters
symbol |
The symbol for the name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.badType(_:)
if symbol
is not a symbol.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
Return Value
The result of calling the method.
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockCall: RbBlockCallback) -> RbObject
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockCall: RbBlockCallback) -> RbObject
Call a Ruby object method using a symbol passing Swift code as a block used immediately.
This version is for something like Enumerable#each
where the block is used
only in the context of this method and never again. The Swift closure does not have
to be escaping or sendable.
If the method you’re calling retains the block in some way, associating it with the called
or returned object for future use, then the Swift closure must be both escaping and sendable
and you must call the method with call(symbol:args:kwArgs:blockRetention:blockCall:)
.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
symbol: any RbObjectConvertible,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:],
blockCall: RbBlockCallback
) throws -> RbObject
Parameters
symbol |
The symbol for the name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
blockCall |
Swift code to pass as a block to the method. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.badType(_:)
if symbol
is not a symbol.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
Return Value
The result of calling the method.
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockRetention: RbBlockRetention, blockCall: RbBlockCallback) -> RbObject
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, blockRetention: RbBlockRetention, blockCall: RbBlockCallback) -> RbObject
Call a Ruby object method using a symbol passing Swift code as a block.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
symbol: any RbObjectConvertible,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:],
blockRetention: RbBlockRetention,
blockCall: @escaping @Sendable RbBlockCallback
) throws -> RbObject
Parameters
symbol |
The symbol for the name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
blockRetention |
Should the |
blockCall |
Swift code to pass as a block to the method. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.badType(_:)
if symbol
is not a symbol.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
Return Value
The result of calling the method.
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, block: any RbObjectConvertible) -> RbObject
func call(symbol: any RbObjectConvertible, args: [(any RbObjectConvertible)?], kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?>, block: any RbObjectConvertible) -> RbObject
Call a Ruby object method using a symbol passing a Ruby Proc as a block.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func call(
symbol: any RbObjectConvertible,
args: [(any RbObjectConvertible)?] = [],
kwArgs: KeyValuePairs<String, (any RbObjectConvertible)?> = [:],
block: any RbObjectConvertible
) throws -> RbObject
Parameters
symbol |
The symbol for the name of the method to call. |
args |
The positional arguments to the method. None by default. |
kwArgs |
The keyword arguments to the method. None by default. |
block |
A Ruby proc to pass as a block to the method. |
Throws
RbError.rubyException(_:)
if there is a Ruby exception.
RbError.badType(_:)
if symbol
is not a symbol.
RbError.duplicateKwArg(_:)
if there are duplicate keywords in kwArgs
.
RbError.badType(_:)
if block
does not convert to a Proc.
Return Value
The result of calling the method.
Attributes
func getAttribute(String) -> RbObject
func getAttribute(String) -> RbObject
Get an attribute of a Ruby object.
Attributes are declared with :attr_accessor
and so on – this routine is a
simple wrapper around call(...)
for symmetry with setAttribute(...)
.
For a version that does not throw, see failable
.
Declaration
Parameters
name |
The name of the attribute to get. |
Throws
RbError.badIdentifier(type:id:)
if name
looks wrong.
RbError.rubyException(_:)
if Ruby has a problem, probably means
attribute
doesn’t exist.
Return Value
The value of the attribute.
func setAttribute(String, newValue: (any RbObjectConvertible)?) -> RbObject
func setAttribute(String, newValue: (any RbObjectConvertible)?) -> RbObject
Set an attribute of a Ruby object.
Attributes are declared with :attr_accessor
and so on – this routine is a
wrapper around a call to the attrname=
method.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func setAttribute(_ name: String, newValue: (any RbObjectConvertible)?)
throws -> RbObject
Parameters
name |
The name of the attribute to set. |
value |
The new value of the attribute. |
Throws
RbError.badIdentifier(type:id:)
if name
looks wrong.
RbError.rubyException(_:)
if Ruby has a problem, probably means
attribute
doesn’t exist.
Return Value
Whatever the attribute setter returns, typically the new value.
Class Variables
func getClassVar(String) -> RbObject
func getClassVar(String) -> RbObject
Get the value of a Ruby class variable that has already been written.
Must be called on an RbObject
for a class, or RbGateway
. Note this
is different from Ruby as-written where you write @@fred
in an object
context to get a CVar on the object’s class.
The behavior of accessing a non-existent CVar is not consistent with IVars or GVars. This is how Ruby works; one more reason to avoid CVars.
For a version that does not throw, see failable
.
Declaration
Parameters
name |
Name of CVar to get. Must begin with ‘@@’. |
Throws
RbError.badIdentifier(type:id:)
if name
looks wrong.
RbError.badType(_:)
if the object is not a class.
RbError.rubyException(_:)
if Ruby has a problem – in particular,
if the CVar does not exist.
Return Value
The value of the CVar.
func setClassVar(String, newValue: (any RbObjectConvertible)?) -> RbObject
func setClassVar(String, newValue: (any RbObjectConvertible)?) -> RbObject
Set a Ruby class variable. Creates a new one if it doesn’t exist yet.
Must be called on an RbObject
for a class, or RbGateway
. Note this
is different from Ruby as-written where you write @@fred = thing
in an
object context to set a CVar on the object’s class.
For a version that does not throw, see failable
.
Declaration
@discardableResult
public func setClassVar(_ name: String, newValue: (any RbObjectConvertible)?)
throws -> RbObject
Parameters
name |
Name of the CVar to set. Must begin with ‘@@’. |
newValue |
The new value to set. |
Throws
RbError.badIdentifier(type:id:)
if name
looks wrong.
RbError.badType(_:)
if the object is not a class.
RbError.rubyException(_:)
if Ruby has a problem.
Return Value
The value that was set.
Global Variables
func getGlobalVar(String) -> RbObject
func getGlobalVar(String) -> RbObject
Get the value of a Ruby global variable.
For a version that does not throw, see failable
.
(This method is present in this class meaning you can call it on any
RbObject
as well as RbGateway
without any difference in effect. This is
purely convenience to put all these getter/setter pairs in the same place and
make construction of RbFailableAccess
a bit easier. Best practice probably
to avoid calling the RbObject
version.)
Declaration
Parameters
name |
Name of global variable to get. Must begin with ‘$’. |
Throws
RbError
if name
looks wrong.
Return Value
Value of the variable, or Ruby nil if not set before.
func setGlobalVar(String, newValue: (any RbObjectConvertible)?) -> RbObject
func setGlobalVar(String, newValue: (any RbObjectConvertible)?) -> RbObject
Set a Ruby global variable. Creates a new one if it doesn’t exist yet.
For a version that does not throw, see failable
.
(This method is present in this class meaning you can call it on any
RbObject
as well as RbGateway
without any difference in effect. This is
purely convenience to put all these getter/setter pairs in the same place and
make construction of RbFailableAccess
a bit easier. Best practice probably
to avoid calling the RbObject
version.)
Declaration
@discardableResult
public func setGlobalVar(_ name: String, newValue: (any RbObjectConvertible)?)
throws -> RbObject
Parameters
name |
Name of global variable to set. Must begin with ‘$’. |
newValue |
New value to set. |
Throws
RbError
if name
looks wrong.
Return Value
The value that was set.
Polymorphic Getter
func get(String) -> RbObject
func get(String) -> RbObject
Get some kind of Ruby object based on the name
parameter:
- If
name
starts with a capital letter then access a constant under this object; - If
name
starts with ‘@’ or ‘@@’ then access an IVar/CVar for a class object; - If
name
starts with ‘$’ then access a global variable; - Otherwise call a zero-args method.
This is a convenience helper to let you access Ruby structures without worrying about precisely what they are.
For a version that does not throw, see failable
.
Declaration
Parameters
name |
Name of thing to access. |
Throws
RbError.rubyException(_:)
if Ruby has a problem.
RbError
of some other kind if name
looks wrong in some way.
Return Value
The accessed thing .