Metaprogramming Ruby: Program Like the Ruby Pros

Author: Paolo Perrotta
4.6
All Stack Overflow 16

Comments

by anonymous   2017-08-20
def make_class(method_name, method_body, s_value)
  Class.new {
    define_method method_name do |*args|
      eval(method_body)
    end

    define_method :to_s do
      s_value
    end
  }
end

"Metaprogramming Ruby: Program Like the Ruby Pros" is a very good book to learn about ruby metaprogramming.

by anonymous   2017-08-20

First read the article in Wikipedia about self (even if it does not mention Ruby at all).

To make a long story short:

  • Ruby has borrowed a lot of concepts from other languages, and self comes from Smalltalk.
  • self is called in Smalltalk a pseudo-variable, which means it is variable, but it is set by the runtime environment, not by the program or programmer.
  • self references all the time the receiver of a message. super references the superclass of that message that is implemented by the method the reference super is in. (Glad that you did not ask for super).
  • self in Ruby (as in Smalltalk) references all the time the current object, and that may be an instance of a class or even a class itself. So if you define methods on the class-side (only callable on the class), even there self references the object, which is the class. So it is possible in Ruby to use only self, you never have to write down the name of the class to denote the receiver. That helps a little bit when refactoring.

If you have get all that, take a look at Metaprogramming Ruby which tells you some more tricks how to use self, classes, eigenclasses and some other interesting things.

by anonymous   2017-08-20

In Ruby local variables only accessible in the scope that they are defined. Whenever you enter/leave a Class, a Module or a Method definiton your scope changes in Ruby.

For instance :

v1 = 1

class MyClass # SCOPE GATE: entering class
  v2 = 2
  local_variables # => ["v2"]

  def my_method # SCOPE GATE: entering def
    v3 = 3
    local_variables  # => ["v3"]
  end # SCOPE GATE: leaving def

  local_variables # => ["v2"]
end # SCOPE GATE: leaving class

These entering and leaving points are called Scope Gates. Since you enter through Scope Gate via method definition you cannot access your local_var inside hello method.


You can use Scope Flattening concept the pass your variable through these gates.

For instance instead of using def for defining your method you can use Module#define_method.

local_var = "Hello"

define_method :hello do
  puts local_var
end

In the same way you can define your classes via Class#New so that your scope does not change when you pass through class definition.

local_var = 'test'

MyClass = Class.new do
  puts local_var #valid
end

instead of

class MyClass
  puts local_var #invalid
end

In the same way you should use Module#New if you want to pass your local variables through Module gates.

Example is taken from Metaprogramming Ruby