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"]
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])
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 (4)
A great article, but I would like to ad more to this concisely that the ruby send method can be used in Ruby to invoke a function in a dynamic manner with a function name in the form of a symbol or a string. The snippet obj. send(“#{method_name}”): This sends the name of the method as stored in the method_name variable to obj. This implies that send enables one to call methods whose names are determined on the run time thus making send solution for providing flexibility in code. For example, suppose method_name is “greet” then obj. # The former produces send("#{method_name}") which is the same as obj. greet().
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?*check if the
attr
is present in the public methodsAnd why not check for
"#{attr}=
as is in the second line where we call it?Ohhhh, that makes sense. I had not processed it like that