Estoy usando el método send() en Ruby para invocar un método que he definido. El método toma un OpenStruct .
Aquí hay un fragmento que muestra cómo invoco mi método usando 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) El problema es que dentro my_method_that_takes_an_openstruct el OpenStruct se envuelve en un Hash , lo que genera un resultado de registro como este:
Just before calling send #<OpenStruct foo="foo"> Inside my_method_that_takes_an_openstruct: {:name_of_openstruct_param=>#<OpenStruct foo="foo">}¿Por qué sucede esto y cómo puedo evitar este comportamiento de envoltura?
Supongo que my_method se parece a esto
class Foo def my_method(arg) puts "#{arg}" end end Si viene de un entorno de Python, podría pensar que podemos llamar my_method como foo.my_method(1) o foo.my_method(arg: 1) . Pero no es así como funciona en Ruby. En Ruby, los argumentos se nombran o son posicionales. Para hacer un argumento nombrado, ponemos dos puntos después de él.
class Foo def my_method(arg:) puts "#{arg}" end end Ahora podemos hacer Foo.new.my_method(arg: 1) o Foo.new.send(:my_method, arg: 1) , pero es incorrecto hacer Foo.new.my_method(1) .
La razón por la que obtienes un hash es un truco de compatibilidad. En versiones antiguas de Ruby, antes de que tuviéramos argumentos con nombre, la convención era tomar un solo argumento hash al final
def foo(a, b, opts) ... endy luego las siguientes dos llamadas serían equivalentes (la primera sería azúcar de sintaxis para la última)
foo(1, 2, foo: "bar", bar: "baz") foo(1, 2, {foo: "bar", bar: "baz"})Básicamente, si aparecía algún argumento con nombre en una lista de argumentos, se convertía en un único hash y se pasaba como argumento final a la función.
Este comportamiento está en desuso a partir de Ruby 2.7 y se eliminó en Ruby 3.0. La convención correcta ahora es tomar argumentos con nombre explícitos, y las versiones recientes de Ruby admiten el operador de doble splat ** para convertir un hash en argumentos con nombre, similar al operador de Python con el mismo nombre.