DEV Community

Cover image for `Send` and `Public Send` in Ruby
Patrick Wendo
Patrick Wendo

Posted on

`Send` and `Public Send` in Ruby

These are methods I learned of when I was learning Ruby and I never understood why they exist or where they'd be used. Regardless, they exist and I finally found out a use case this weekend.

First off, what is Send and Public Send? (According to the docs send and public send)

Send: Invokes the method identified by symbol, passing it any arguments specified. You can use send if the name send clashes with an existing method in obj. When the method is identified by a string, the string is converted to a symbol.

Public Send : Invokes the method identified by symbol, passing it any arguments specified. Unlike send, public_send calls public methods only. When the method is identified by a string, the string is converted to a symbol.

I was building a helper in rails for forms to auto-generate the input tags for specific model fields, so I'd define an array like this

cols = ["first_name", :user, :first_name, "text"]
Enter fullscreen mode Exit fullscreen mode

Where we have the tag's name, the model, the field, and the tag type in that order. This array is then sent to the view where the tags are built based on the contents of the array.

This was done to access the model in such a way that I do not have to hard code it for specific models(as is the case of associated models and such). I was using public send like this

cols[1]&.public_send(col[2])
Enter fullscreen mode Exit fullscreen mode

This will call only the public method named in cols[2] of the model named in cols[1].

I can't think of another use case for public_send and send, so if you're a ruby veteran, please let me know down below if you have used it before.

Top comments (6)

Collapse
 
jeremyf profile image
Jeremy Friesen

Public send is great for method dispatch.

Here are links to two examples in the Forem code-base:

github.com/forem/forem/blob/9bd936...

github.com/forem/forem/blob/9bd936...

Collapse
 
w3ndo profile image
Patrick Wendo
next if public_send(attr).present?

public_send("#{attr}=", nil)
Enter fullscreen mode Exit fullscreen mode

I am having trouble understanding this part. Does the first line just check if attr is present, and then the second one actually do the public send?

Collapse
 
jeremyf profile image
Jeremy Friesen
next if name.present?

self.name = nil
Enter fullscreen mode Exit fullscreen mode

The above is equivalent if the attr variable is :name.

Thread Thread
 
w3ndo profile image
Patrick Wendo

Ohhhh, that makes sense. I had not processed it like that

Collapse
 
w3ndo profile image
Patrick Wendo

*check if the attr is present in the public methods

And why not check for "#{attr}= as is in the second line where we call it?

Thread Thread
 
jeremyf profile image
Jeremy Friesen

To refine, attr is the name of the method (e.g. name) and "#{attribute}=" is the name= method.