Executes the given block within the context of the receiver (obj). In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj's instance variables. Arguments are passed as block parameters.
BasicObject#instance_exec
We can use instance_exec
to implement FactoryBot-like factory method. Given the following
class User
attr_accessor :name, :email
end
FactoryMaker.factory(User) do
name { "Juanito" }
email { "[email protected]" }
end
The above example shows we want to do something like this given this User
class:
user = User.new
user.name = "Me"
user.email = "[email protected]"
But instead we want to do it in the above block-style. Let’s see how to implement this.
FactoryMaker.factory(User) do
...
end
Here we pass in a User
and a block to FactoryMaker.factory
. We want to use the given class to instantiate a new user instance and set the instance variables accordingly.
class FactoryMaker
def self.factory(klass, &block)
ObjectMaker.new(klass).instance_exec(&block)
end
class ObjectMaker
def initialize(klass)
@object = klass.new
end
def method_missing(name, *args, &block)
self.object.instance_variable_set(
"@#{name}",
block.call,
)
object
end
private
attr_accessor :object
end
end
Hope this helps :)