These below are the available scopes where you can evaluate your code:

1. Instance Scope : (instance_eval, instance_exec)

2. Class Scope / Module Scope: (class_eval, class_exec, module_eval, module_exec)

Scopes in simple term is the area of visibility and accessibility. Out of that area, things are not valid and does not mean anything.

1. Instance Scope: Things available for one instance of the class.
Variables and methods which varies for the different instance of the class.

Instance_eval / instance_exec

The above methods are used to evaluate an arbitrary code in the context of an instance of class or object of a class.

Let’s see an example

class SecretKlass
    def initialize
        @secret = 99
    end
    private
    def secret_method
        "secret method called"
    end
end

s = SecretKlass.new

#Input

puts s.instance_eval { @secret }
puts s.instance_eval { secret_method }
puts s.instance_eval {|obj| obj==self}

#output
99
secret method called
true

As you can see private methods are also called.

Let’s take a look at another example:

class KlassSecret
    def initialize
        @secret = 99
    end
end

k = KlassSecret.new

k.instance_exec(5) { |x| @secret + x } #= > 104

foo = 42

k.instance_eval { @secret + foo } #141

puts k.instance_eval {@secret} #99

As you can see in the above example, it is not changing the value of @secret instance variable.

class_eval / class_exec

These methods are for evaluating an arbitrary in the context of the class.

Class SomeThing
end

SomeThing.class_exec do
    def hello_world
        “hello world”
    end
end

puts SomeThing.new.hello_world() #hello world

module_exec and module_eval are the same as class_exec and class_eval
as we already know module is similar to classes and may hold the collection of constants, variables methods module and class definitions.

Evaluating String Code with eval

Binding:

Binding is the object of Binding class which encapsulate the execution context at some particular place in the code and retain this context for the later use.

def get_binding(str)
    return binding
end

str = "hello"

puts eval " str + ' Remo '"
puts eval " str + ' name ' "
puts eval " str + 'mark' ", get_binding('bye ')

Calling Methods: send, public_send

Send method from the standard ruby library is used to call the methods of any class.
Send method is used on the instance of any class and from that instance we can call any method from access specifiers whether its a public, private or protected method.

send method invokes the method identified by the symbol which is passed to it as an argument.

public_send method is same as send method but it only calls the public methods of the instance for the class.

__send__ method is exactly the same as send but it is used when the send method is clashing with the methods of the existing methods of that object.

Take look at the below code for better understanding

class ClassName
    def fuse
        "public fuse"
    end
    private
    def zap
        "private zap"
    end
end

obj = ClassName.new

puts obj.send(:fuse) #”public fuse”
puts obj.send(:zap) #”private zap”
puts obj.zap

#private method `zap' called fo #<ClassName:0x00000001041d88> (NoMethodError)

puts obj.public_send(:zap)
#private method `zap' called for #<ClassName:0x00000001041d88> (NoMethodError)

puts obj.public_send(:fuse)             # “public fuse”

puts obj.__send__(:zap) # “private zap”

puts obj.__send__(:fuse) # “private fuse”