Search code examples
rubymethodsargumentssendsplat

Ruby send using splat not working as expected


I have a services class that helps sanitize data from a JSON payload.

  attr_reader :data, :method, :args

  def self.call(*args)
    new(*args).call
  end

  def initialize(data, sanitization_method, *method_args)
    @data = data
    @method = sanitization_method
    @args = *method_args
  end

  def call
    data.send(method, args)
  end

The problem is when I call the class method, it returns an Enumerator:

PaidGigs::Services::SanitizeData.call("shd234", :gsub, /[^0-9]/, "")

=>  #<Enumerator: "shd234":gsub([/[^0-9]/, ""])>

Instead of evaluating the method and returning:

=> "234"

I've played around in the console and it is because the splat array isn't being converted to individual arguments, which is contrary to what the Ruby docs suggest. Has anyone had this issue with Object#send? Any help greatly appreciated!


Solution

  • You should store the args as an Array and use splat at the last moment:

    class SanitizeData
      attr_reader :data, :method, :args
    
      def self.call(*args)
        new(*args).call
      end
    
      def initialize(data, sanitization_method, *method_args)
        @data = data
        @method = sanitization_method
        @args = method_args
      end
    
      def call
        data.send(method, *args)
      end
    end
    
    puts SanitizeData.call("shd234", :gsub, /[^0-9]/, "").inspect