Project

General

Profile

Actions

Bug #12136

closed

OpenStruct.new(format: :bar).send :format # => too few arguments

Added by niko (Niko Dittmann) over 8 years ago. Updated about 4 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
[ruby-core:74094]
Tags:

Description

#send(:format) to an OpenStruct with a field named :format raises an ArgumentError in Ruby 2.3.0:

OpenStruct.new(format: :bar).send :format
ArgumentError: too few arguments

It works as expected in ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux] and with any other method name I tried:

OpenStruct.new(f: :bar).send :f
=> :bar

String or Symbol in the OpenStruct definition and as argument of #send make no difference.


Related issues 3 (0 open3 closed)

Related to Ruby master - Bug #12251: DelegateClass(OpenStruct) behavior in 2.3.0 different from 2.2ClosedActions
Related to Ruby master - Bug #15409: OpenStruct error when attribute is called 'method'Closedmarcandre (Marc-Andre Lafortune)Actions
Related to Ruby master - Bug #18032: Openstruct is ~20..25x slower with Ruby 3.0.0 and 3.0.1 compared to earlier versionsRejectedmarcandre (Marc-Andre Lafortune)Actions

Updated by niko (Niko Dittmann) over 8 years ago

It's this commit: https://github.com/ruby/ruby/blob/7fa21558051e5412dcb790f528e392476edd4389/lib/ostruct.rb

By defining the getters and setters lazily the Kernel, Object and BasicObject instance methods shine through and #method_missing doesn't kick in. Therefor the #send semantics is broken for methods colliding with methods defined in parent classes.

Updated by marcandre (Marc-Andre Lafortune) over 8 years ago

Indeed, latest optimization of OpenStruct now allows conflicts with Object private methods.

I didn't realize it, but conflicts with public methods are already ignored (i.e. OpenStruct.new(hash: 'code').hash does not return 'code)

Note that OpenStruct.new(format: :bar).public_send :format does return :bar.

Possibilities:

a) Keep behavior the same and rubyists can alleviate these by using public_send instead of send

b) Modify new to check for conflict between keys and Object private instance methods and define actual methods in these cases.

c) Revert optimization. Optionally create OpenStruct.lazy for the optimized version.

I'm in favor for the later, but maybe I'm missing alternatives?

BTW, I thought at first that we could undefine private instance methods of OpenStruct, except for the usual callbacks and modify respond_to_missing? + method_missing so that calls to these private methods still work.

Sadly, there's no way to know from method_missing if that method is called privately or publicly, so this would effectively make all private methods become public which is not acceptable.

Updated by Eregon (Benoit Daloze) over 8 years ago

Marc-Andre Lafortune wrote:

Sadly, there's no way to know from method_missing if that method is called privately or publicly, so this would effectively make all private methods become public which is not acceptable.

There is a way now, mentioned in #12113. I'm not sure whether it is good idea to use it, though.

Actions #4

Updated by marcandre (Marc-Andre Lafortune) over 8 years ago

  • Related to Bug #12251: DelegateClass(OpenStruct) behavior in 2.3.0 different from 2.2 added

Updated by dblock (Daniel Doubrovkine) over 8 years ago

a) Keep behavior the same and rubyists can alleviate these by using public_send instead of send

It doesn't seem that swapping send by public_send has any effect, at least not in the example in #12251.

Is there a workaround for existing code that would make things work the way it worked in Ruby 2.2.x?

Actions #6

Updated by marcandre (Marc-Andre Lafortune) over 8 years ago

  • Has duplicate Bug #12349: Can't load OpenStruct with Syck with Ruby 2.3.x added
Actions #7

Updated by marcandre (Marc-Andre Lafortune) over 8 years ago

  • Has duplicate deleted (Bug #12349: Can't load OpenStruct with Syck with Ruby 2.3.x)
Actions #8

Updated by marcandre (Marc-Andre Lafortune) about 5 years ago

  • Related to Bug #15409: OpenStruct error when attribute is called 'method' added
Actions #9

Updated by jeremyevans0 (Jeremy Evans) about 4 years ago

  • Status changed from Open to Closed
Actions #10

Updated by mame (Yusuke Endoh) over 3 years ago

  • Related to Bug #18032: Openstruct is ~20..25x slower with Ruby 3.0.0 and 3.0.1 compared to earlier versions added
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0