Search code examples
rubysyntaxcoding-style

When can I safely call send method on objects in Ruby?


I know it is a good practice to call public_send instead of send on objects so as not to unintentionally call a private method. However, if I know that the methods I will be calling are public for sure, can I use send? I have written this code:

[:name, :artist, :album,].each do |attribute|
  define_method "#{attribute}s" do
    @songs.map { |song| song.public_send(attribute) }.uniq
  end
end

Would it be considered bad practice if I replace public_send with send here?


Solution

  • TLDR;

    Calling send is fine, it's inside your class.

    Full Explanation

    Alex, Here is what I have always thought about this tactic. I believe that this is well inline with the community.

    The Ruby Docs say this about 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.

    This is a public method accessible to anyone in the world. That means anyone using your code can call private functions whenever they want!

    Thus... you shouldn't really think in terms of public and private functions as you would in other languages. I would argue you change your definitions a little bit.

    Public: Well-tested, robust, error-checked functions which are recommended for use by the world.

    Private: Helper functions which may accept invalid input and break things.

    I don't have some big rationale for this, just an overall impression about how these concepts work in Ruby.

    For your specific problem its important to remember that you are the one coding this up, and I assume that your code is within a class you created. In that case, I use send all the time! It's shorted than public_send and I know exactly what I'm calling!

    You will want to document it well enough so that anyone coming behind you will know what to be careful of.