Module: Candor

Defined in:
lib/candor.rb,
lib/candor/definer.rb,
lib/candor/version.rb,
lib/candor/signature.rb

Overview

Turns a block or a callable into a real method with an honest signature: the body's arity, the body's parameters, the body's source_location, and allocation-free dispatch.

Candor.define(MyClass, :greet) { |name, greeting: "hi"| "#{greeting}, #{name}" }
MyClass.instance_method(:greet).parameters # => [[:req, :__p0], [:key, :greeting]]

A wrong-arity call and an unknown keyword raise ArgumentError at the fabricated method, before anything of yours runs.

Defined Under Namespace

Classes: Signature

Constant Summary collapse

BODY_PREFIX =

Prefix of the private methods holding compiled bodies. Fabricated names may not start with it, and an interceptor reaches its body through body_name.

"__candor_body_"
VERSION =

The gem version.

"0.2.0"

Class Method Summary collapse

Class Method Details

.body_name(name) ⇒ Symbol

The private method holding a fabricated method's body. An interceptor calls it with send.

Parameters:

  • name (Symbol)

    a canonical name

Returns:

  • (Symbol)


64
# File 'lib/candor.rb', line 64

def body_name(name) = :"#{BODY_PREFIX}#{name}"

.define(target, name, aliases: [], via: nil, parameters: nil, source_location: nil, body: nil) { ... } ⇒ Symbol

Defines a real method on target whose signature is the body's.

With via, every call routes to that method on the target as via(canonical_name, ...), and it alone decides whether to run the body — which it reaches under body_name. Without via, the wrapper forwards straight to the body.

An unpassed optional is dropped from the forwarded arguments, so the body applies its own default.

Candor.define(App.singleton_class, :fetch, aliases: [:get], via: :__call) { |id, ttl: 60| ... }

Parameters:

  • target (Module)

    the module — often a singleton_class — to install onto

  • name (Symbol)

    the canonical name, passed to the interceptor and used for the body method

  • aliases (Array<Symbol>) (defaults to: [])

    further names sharing the one dispatch and the one canonical name

  • via (Symbol, nil) (defaults to: nil)

    an interceptor method on target, resolved per call

  • parameters (Array<Array>, nil) (defaults to: nil)

    an explicit shape advertised instead of the body's; not validated against the body, so a mismatch surfaces as the body's own ArgumentError

  • source_location (Array(String, Integer), nil) (defaults to: nil)

    a location reported instead of the body's, for a caller whose body is a proc it generated on the user's behalf; also the only way to fabricate from a body carrying no location of its own

  • body (Proc, Method, UnboundMethod, nil) (defaults to: nil)

    the body, when it is not given as a block

Yields:

  • the body, when it is not given as body; self inside it is the receiver

Returns:

  • (Symbol)

    the canonical name

Raises:

  • (TypeError)

    if target is not a Module, or the body is neither a block, a Proc, a Method nor an UnboundMethod, or neither it nor source_location carries a location, or the body's owner is not an ancestor of target

  • (ArgumentError)

    if a name starts with BODY_PREFIX, or via is not a callable method name, or parameters or source_location is malformed

  • (FrozenError)

    if target is frozen



55
56
57
58
# File 'lib/candor.rb', line 55

def define(target, name, aliases: [], via: nil, parameters: nil, source_location: nil, body: nil, &block)
  Definer.new(target, name, aliases: aliases, via: via, parameters: parameters,
                            source_location: source_location, body: body || block).call
end