0

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!

Jay
  • 493
  • 5
  • 14

2 Answers2

1

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
Thomas
  • 1,613
  • 8
  • 8
  • Excellent! Thank you. Assuming calling the splat actually does something to break apart the array? – Jay Nov 03 '14 at 18:13
  • I would say that splat turns an argument list into an array or an array into an argument list. – Thomas Nov 03 '14 at 18:22
1

You're storing the args as an array, so when you call that method, you need to splat it again:

def call
  data.send(method, *args)
end

And this:

@args = *method_args

The splat does nothing for you, so it can just be:

@args = method_args
Nick Veys
  • 23,458
  • 4
  • 47
  • 64