Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

380
Views
Ruby: why are inputs passed to send() being wrapped in a Hash?

I'm using the send() method in Ruby to invoke a method I've defined. The method takes an OpenStruct.

Here's a snippet showing how I invoke my method using send:

my_open_struct = OpenStruct.new(foo: "foo")

result = @my_object.send(
            :my_method_that_takes_an_openstruct,
            name_of_openstruct_param: my_open_struct)

The problem is that inside my_method_that_takes_an_openstruct the OpenStruct param is getting wrapped in a Hash, resulting in logging output like this:

Just before calling send #<OpenStruct foo="foo">
Inside my_method_that_takes_an_openstruct: {:name_of_openstruct_param=>#<OpenStruct foo="foo">}

Why is this happening, and how can I prevent this wrapping behaviour?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

I'm assuming my_method looks something like this

class Foo
  def my_method(arg)
    puts "#{arg}"
  end
end

If you're coming from a Python background, you might think we can call my_method as either foo.my_method(1) or foo.my_method(arg: 1). But this isn't how it works in Ruby. In Ruby, arguments are either named or positional. To make an argument named, we put a colon after it.

class Foo
  def my_method(arg:)
    puts "#{arg}"
  end
end

Now we can do Foo.new.my_method(arg: 1) or Foo.new.send(:my_method, arg: 1), but it's incorrect to do Foo.new.my_method(1).

The reason you're getting a hash is a compatibility trick. In old versions of Ruby, before we had named arguments, the convention was to take a single hash argument at the end

def foo(a, b, opts)
  ...
end

and then the following two calls would be equivalent (the former being syntax sugar for the latter)

foo(1, 2, foo: "bar", bar: "baz")
foo(1, 2, {foo: "bar", bar: "baz"})

Basically, if any named-looking arguments appeared in an argument list, they'd get converted to a single hash and passed as the final argument to the function.

This behavior is deprecated as of Ruby 2.7 and removed in Ruby 3.0. The correct convention now is to take explicit named arguments, and recent versions of Ruby support the double splat ** operator for converting a hash into named arguments, similar to the Python operator with the same name.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!