rubydouble-splat

Make Ruby object respond to double splat operator **


I have a library that has an #execute method like this

def execute(query, **args)
  # ...
end

I have a class that generates the data for args (which has a lot of logic depending on user abilities)

class Abilities
  def to_h
    { user: user } # and a lot more data
  end
end

Now when I'm using #execute I always have to remember to use #to_h, which is pretty annoying and leads to mistakes when someone forgets it:

execute(query, abilities.to_h)

So I was wondering if my Abilities class could somehow respond to the ** (double splat) operator, so that I can simply pass the object:

execute(query, abilities)

When I try to call it like this, it throws an error:

ArgumentError: wrong number of arguments (given 2, expected 1)

So, is there any way to make my Abilities class behave like a Hash? I could derive it like this Abilities < Hash but then I have all the Hash logic on it, which seems pretty dirty.


Solution

  • You can implement to_hash: (or define it as an alias for to_h)

    class MyClass
      def to_hash
        { a: 1, b: 2 }
      end
    end
    
    def foo(**kwargs)
      p kwargs: kwargs
    end
    
    foo(MyClass.new)
    #=> {:kwargs=>{:a=>1, :b=>2}}