Ruby’s Send Method — Why It’s Important.

Yehuda Bortz
2 min readDec 3, 2020

--

While creating COVID Stats CLI there were a number of obstacles restricting me from creating a dynamic and flexible application. Most notably was how to deal with creating and managing attribute readers and writers.

Due to the nature of the API I’m using I needed to have access to many different key/value pairs.

Heres an example of an array with hashes inside it. Iteration was needed over the array in order to create a new instance of my Country class from each hash.

[{"country" => "USA", "cases" => 1234},
{"country" => "Norway", "cases" => 450}]

I also needed to assign attribute readers and writers for each key/value pair in order that I could access them from outside the Country class. I could have done this by manually defining each attribute reader/writer using Ruby’s attr_accessor.

For example:

attr_accessor :country, :cases

This, however, would be tedious given that there are many key/value pairs and they are subject to change on the API side of things. So, this is where the–

send

– method comes into play. It allows me to dynamically and at mass, assign all the attr_accessors for each key/value pair defined in each hash.

What does send do?

In the simple form send invokes a method.

For example:

class Name
def say_hi_to(name)
"Hi #{name}"
end
end
example = Name.new
example.send :say_hi_to, "Yehuda"
=> "Hi Yehuda"

Now that example wasn’t so special because we could have just done this —

class Name
def say_hi_to(name)
"Hi #{name}"
end
end
example = Name.new
example.say_hi_to("Yehuda")
=> "Hi Yehuda"

The send method stands out when we don’t yet know the name of a variable. Under the hood of attr_accessor we are creating an attribute reader and an attribute writer, normally created like —

For example:

# attribute readerdef name
@name
end
# attribute writerdef name=(value)
@name = value
end

attr_accessor is just a ruby method for accomplishing the above snippet.

attr_accessor :name

So we can use this method with send to iterate over our key/value pairs that are being passed into our initialize method upon the creation of a new instance in our Class.

For example:

attributes = {"country" => "USA", "cases" => 1234}class Country
def initialize(attributes)
attributes.each do |key, value|
self.class.attr_accessor(key)
self.send(("#{key}="), value)
end
end
end

If we create a new instance of our Country class –

new_country = Country.new(attributes)
=> #<Country:0x00007fcd178b4d68 @country="USA", @cases=1234>

– and then call our new class instance with our instance variable after it, we will be able to read that data.

new_country.country
=> "USA"

In Conclusion

Now we see the power of send. Since we are iterating over our attributes hash and using the send method on each pass to set the attr_accessor’s we end up with the reader’s and writer’s that we require. No more, no less.

--

--

No responses yet