class SimpleDelegator - Documentation for Ruby 4.0
Description: class SimpleDelegator: A concrete implementation of Delegator, this class provides the means to delegate all supported method calls to the object passed into the constructor
Keywords: ruby,class,SimpleDelegator

🔍

No recent searches

# class SimpleDelegator

A concrete implementation of `Delegator`, this class provides the means to delegate all supported method calls to the object passed into the constructor and even to change the object being delegated to at a later time with `__setobj__`.

    class User
      def born_on
        Date.new(1989, 9, 10)
      end
    end

    require 'delegate'

    class UserDecorator < SimpleDelegator
      def birth_year
        born_on.year
      end
    end

    decorated_user = UserDecorator.new(User.new)
    decorated_user.birth_year  #=> 1989
    decorated_user.__getobj__  #=> #<User: ...>

A `SimpleDelegator` instance can take advantage of the fact that `SimpleDelegator` is a subclass of `Delegator` to call `super` to have methods called on the object being delegated to.

    class SuperArray < SimpleDelegator
      def [](*args)
        super + 1
      end
    end

    SuperArray.new([1])[0]  #=> 2

Here’s a simple example that takes advantage of the fact that SimpleDelegator’s delegation object can be changed at any time.

    class Stats
      def initialize
        @source = SimpleDelegator.new([])
      end

      def stats(records)
        @source.__setobj__(records)

        "Elements:  #{@source.size}\n" +
        " Non-Nil:  #{@source.compact.size}\n" +
        "  Unique:  #{@source.uniq.size}\n"
      end
    end

    s = Stats.new
    puts s.stats(%w{James Edward Gray II})
    puts
    puts s.stats([1, 2, 3, nil, 4, 5, 1, 2])

Prints:

    Elements:  4
     Non-Nil:  4
      Unique:  4

    Elements:  8
     Non-Nil:  7
      Unique:  6

### Public Instance Methods

__getobj__ () { || ... }
Source

    # File lib/delegate.rb, line 319
    def __getobj__
      unless defined?(@delegate_sd_obj)
        return yield if block_given?
        __raise__ ::ArgumentError, "not delegated"
      end
      @delegate_sd_obj
    end

Returns the current object method calls are being delegated to.

__setobj__ (obj)
Source

    # File lib/delegate.rb, line 341
    def __setobj__(obj)
      __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
      @delegate_sd_obj = obj
    end

Changes the delegate object to obj.

It’s important to note that this does not cause SimpleDelegator’s methods to change. Because of this, you probably only want to change delegation to objects of the same type as the original delegate.

Here’s an example of changing the delegation object.

    names = SimpleDelegator.new(%w{James Edward Gray II})
    puts names[1]    # => Edward
    names.__setobj__(%w{Gavin Sinclair})
    puts names[1]    # => Sinclair