Macro rutie::methods

source ·
macro_rules! methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ident $body: block
        )*
    ) => { ... };
}
Expand description

Creates callbacks for Ruby methods

Unlike unsafe_methods!, this macro is safe, because:

  • it uses safe conversions of arguments (Object::try_convert_to());
  • it checks if arguments are present;

Each argument will have type Result<Object, AnyException>.

For example, if you declare number: Fixnum in the method definition, it will have actual type number: Result<Fixnum, AnyException>.

See examples below and docs for Object::try_convert_to() for more information.

Examples

To launch a server in Rust, you plan to write a simple Server class

class Server
  def start(address)
  end
end

The address must be Hash with the following structure:

{
  host: 'localhost',
  port: 8080,
}

You want to extract port from it. Default port is 8080 in case when:

  • address is not a Hash
  • address[:port] is not present
  • address[:port] is not a Fixnum
#[macro_use]
extern crate rutie;

use rutie::{Class, Fixnum, Hash, NilClass, Object, Symbol, VM};

class!(Server);

methods!(
    Server,
    itself,

    fn start(address: Hash) -> NilClass {
        let default_port = 8080;

        let port = address
            .map(|hash| hash.at(&Symbol::new("port")))
            .and_then(|port| port.try_convert_to::<Fixnum>())
            .map(|port| port.to_i64())
            .unwrap_or(default_port);

        // Start server...

        NilClass::new()
    }
);

fn main() {
    Class::new("Server", None).define(|itself| {
        itself.def("start", start);
    });
}

Ruby:

class Server
  def start(address)
    default_port = 8080

    port =
      if address.is_a?(Hash) && address[:port].is_a?(Fixnum)
        address[:port]
      else
        default_port
      end

  end
end