Other ways to interact with an object

Usual way that you interact with an object inside your ruby code is by injecting the dependency (hopefully), but Ruby gives us some really powerful ways on how to interact with object in different ways thanks to procs and lambdas. These first order functions provide us with really flexible way to create a DSL, configuration class or do some work in the middle of method. Let's explore some of the options that we have:

Passing self to a block

First example is very straight forward and easy. We just pass "self" which represents the object in given class to the block that we are interacting with and call a methods on it as a regular object (In our example it is a class).
You will see this technique commonly used in configurations:

Configuration.config do |c|
  c.allow_ssl = true
  c.cert_path = "/var/www"

The goal here is to define class attributes that can be accessed trough out your application. We usually want to keep them in one place, that's why it is good idea to hold them as class attributes.

class Configuration
  class << self
    def config
    attr_accessor :allow_ssl, :cert_path

By passing self to yield you are passing given object to the block and thus allowing to interact with it like a normal object.

Of course no one prohibits from using it inside of an instance. Let's try to implement something that can be ran and customised in the middle of method execution:

class InMiddleExample
  def in_middle_of_job
  def do_before_job
    puts "Before job"
  def do_after_job
    puts "After job"
  def some_other_work
    puts "Some other work"

InMiddleExample.new.in_middle_of_job do |o|
  puts "In the middle of job"

Sure enough, if you launch this code in your IRB console, your result will be:

Before job
Some other work
In the middle of job
After job
=> nil

Passing a lambda for delayed execution

I have covered this topic in my previous post: Callbacks and Ruby But this might be useful to recap (even for myself):

class LambdaExample
  def initialize(callback)
    @callback = callback
  attr_reader :callback
  def say_hello_from_lambda

lambda_example = LambdaExample.new(
	->(greeting) do
    	puts "#{greeting} Janis"


As you can see, execution is delayed until you call say_hello_from_lambda
which calls .call on the lambda and executes it. (Too much "call") :)

[12] pry(main)> lambda_example.say_hello_from_lambda 
Hello Janis

Switching the context

We are used to calling method on objects like so object.method_call What if you want to switch context in order to call methods inside of other object using block? Thats actually pretty simple to do with instance_eval method which accepts blocks or strings of code to evaluate. This technique is commonly used inside of DSL's like Rspec with it's describe, it and context blocks

class InstanceEvalExample
  def switch_context(&block)
  def say_hello_from_other_classes_context
  	puts "Hello"

instance_eval_example = InstanceEvalExample.new

Now you can call this objects methods inside of the block.

[17] pry(main)> instance_eval_example.switch_context do
[17] pry(main)*   say_hello_from_other_classes_context  
[17] pry(main)* end  

The reason it works that way is because instance eval ,for the time of execution of proc, is switching context or in other words switches self to given instance of InstanceEvalExample

Ruby allows us a lot of flexibility when dealing with objects and these are only three ways of doing that. I am pretty sure there are other ones, but these are most common ones. Hope you enjoyed.

Janis Miezitis

Read more posts by this author.

Subscribe to Janis Miezitis personal blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!