sonic-pi

https://github.com/sonic-pi-net/sonic-pi

C++

Code. Music. Live.

Module#delegate

Provides a +delegate+ class method to easily expose contained objects'
public methods as your own.

==== Options
* <tt>:to</tt> - Specifies the target object
* <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
* <tt>:allow_nil</tt> - if set to true, prevents a +NoMethodError+ to be raised

The macro receives one or more method names (specified as symbols or
strings) and the name of the target object via the <tt>:to</tt> option
(also a symbol or string).

Delegation is particularly useful with Active Record associations:

  class Greeter < ActiveRecord::Base
    def hello
      'hello'
    end

    def goodbye
      'goodbye'
    end
  end

  class Foo < ActiveRecord::Base
    belongs_to :greeter
    delegate :hello, to: :greeter
  end

  Foo.new.hello   # => "hello"
  Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>

Multiple delegates to the same target are allowed:

  class Foo < ActiveRecord::Base
    belongs_to :greeter
    delegate :hello, :goodbye, to: :greeter
  end

  Foo.new.goodbye # => "goodbye"

Methods can be delegated to instance variables, class variables, or constants
by providing them as a symbols:

  class Foo
    CONSTANT_ARRAY = [0,1,2,3]
    @@class_array  = [4,5,6,7]

    def initialize
      @instance_array = [8,9,10,11]
    end
    delegate :sum, to: :CONSTANT_ARRAY
    delegate :min, to: :@@class_array
    delegate :max, to: :@instance_array
  end

  Foo.new.sum # => 6
  Foo.new.min # => 4
  Foo.new.max # => 11

It's also possible to delegate a method to the class by using +:class+:

  class Foo
    def self.hello
      "world"
    end

    delegate :hello, to: :class
  end

  Foo.new.hello # => "world"

Delegates can optionally be prefixed using the <tt>:prefix</tt> option. If the value
is <tt>true</tt>, the delegate methods are prefixed with the name of the object being
delegated to.

  Person = Struct.new(:name, :address)

  class Invoice < Struct.new(:client)
    delegate :name, :address, to: :client, prefix: true
  end

  john_doe = Person.new('John Doe', 'Vimmersvej 13')
  invoice = Invoice.new(john_doe)
  invoice.client_name    # => "John Doe"
  invoice.client_address # => "Vimmersvej 13"

It is also possible to supply a custom prefix.

  class Invoice < Struct.new(:client)
    delegate :name, :address, to: :client, prefix: :customer
  end

  invoice = Invoice.new(john_doe)
  invoice.customer_name    # => 'John Doe'
  invoice.customer_address # => 'Vimmersvej 13'

If the target is +nil+ and does not respond to the delegated method a
+NoMethodError+ is raised, as with any other value. Sometimes, however, it
makes sense to be robust to that situation and that is the purpose of the
<tt>:allow_nil</tt> option: If the target is not +nil+, or it is and
responds to the method, everything works as usual. But if it is +nil+ and
does not respond to the delegated method, +nil+ is returned.

  class User < ActiveRecord::Base
    has_one :profile
    delegate :age, to: :profile
  end

  User.new.age # raises NoMethodError: undefined method `age'

But if not having a profile yet is fine and should not be an error
condition:

  class User < ActiveRecord::Base
    has_one :profile
    delegate :age, to: :profile, allow_nil: true
  end

  User.new.age # nil

Note that if the target is not +nil+ then the call is attempted regardless of the
<tt>:allow_nil</tt> option, and thus an exception is still raised if said object
does not respond to the method:

  class Foo
    def initialize(bar)
      @bar = bar
    end

    delegate :name, to: :@bar, allow_nil: true
  end

  Foo.new("Bar").name # raises NoMethodError: undefined method `name'

The target method must be public, otherwise it will raise +NoMethodError+.

Source | Google | Stack overflow

Edit

git clone [email protected]:sonic-pi-net/sonic-pi.git

cd sonic-pi

open app/server/ruby/vendor/activesupport-7.0.6/lib/active_support/core_ext/module/delegation.rb

Contribute

# Make a new branch

git checkout -b -your-name--update-docs-Module-delegate-for-pr


# Commit to git

git add app/server/ruby/vendor/activesupport-7.0.6/lib/active_support/core_ext/module/delegation.rbgit commit -m "better docs for Module#delegate"


# Open pull request

gem install hub # on a mac you can `brew install hub`

hub fork

git push <your name> -your-name--update-docs-Module-delegate-for-pr

hub pull-request


# Celebrate!