Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undefined method `extract_ruby_args=' for module IRB::Command (NoMethodError) #958

Closed
rebuilt opened this issue May 21, 2024 · 8 comments · Fixed by #961
Closed

undefined method `extract_ruby_args=' for module IRB::Command (NoMethodError) #958

rebuilt opened this issue May 21, 2024 · 8 comments · Fixed by #961

Comments

@rebuilt
Copy link

rebuilt commented May 21, 2024

Description

In a rails console, running the following command fails measure = Measure.first
But the following succeeds m = Measure.first

The error message of the measure = Measure.first command is

(eval at /home/nelson/.asdf/installs/ruby/3.3.1/lib/ruby/gems/3.3.0/gems/irb-1.13.1/lib/irb/command/internal_helpers.rb:22):1:in `<main>': undefined method `extract_ruby_args=' for module IRB::Command (NoMethodError)

IRB::Command.extract_ruby_args = Measure.first

Maybe IRB bug!

When I revert to using irb version 1.12.0 all commands work correctly, but on versions 1.13.0 and 1.13.1, the command fails as described above.

I have other models in my application but so far, only measure.rb fails in this way. I'm still testing to see if the problem affects any other model.

Result of irb_info

Ruby version: 3.3.1
IRB version: irb 1.13.1 (2024-05-05)
InputMethod: RelineInputMethod with Reline 0.5.7
Completion: Autocomplete, RegexpCompletor
RUBY_PLATFORM: x86_64-linux
LANG env: en_US.UTF-8
East Asian Ambiguous Width: 1

Terminal Emulator

What's your terminal emulator?
Kitty

Setting Files

Are you using ~/.irbrc and ~/.inputrc?
No

@rebuilt
Copy link
Author

rebuilt commented May 21, 2024

I assume there's a clash with the irb command
measure measureenables the mode to measure processing time.measure :off disables it.

@tompng
Copy link
Member

tompng commented May 22, 2024

measure = 1 is a measure command call with args = "= 1". Related to #803.
The error message is not user friendly so it should be improved.

@Earlopain
Copy link

I ran into the same thing when trying to assign some source code string to a variable named source. I guess this would be because of #824? Not seeing much else in the changelog.

I was curious how python handles this: its repl also has some buildins. The help command for example works, as long as you don't reassign it. exit as well, which means you can only close with ctrl+d, not with exit() anymore. I believe irb should do the same.

@st0012
Copy link
Member

st0012 commented May 25, 2024

In #824, we decided commands should always take precedence over variable names or methods (mostly my idea tbf). This is to avoid situations like having help in the scope of the binding.irb breakpoint unexpectedly disabling the command completely.

But now I think we can do a more sophisticated check to support this precedence order:

  1. Local variables defined in the IRB session
  2. Command name
  3. Local variables or methods in the program context

So in this example:

help = 1
binding.irb

when users type help in the IRB console, it'd execute the command.
But if users do help = 1, we should allow it, and the subsequent help call would retrieve the local variable instead.

WDYT @tompng?

@tompng
Copy link
Member

tompng commented May 25, 2024

I think it is hard to distinguish local variables defined in program context from local variables defined in IRB session, especially when using chws or rdbg command. And I think the behavior is complex/hard to understand for user.

How about simply make the precedence:

  1. Local variables
  2. Command name
  3. Methods

(This will be a simpler version of #803 (comment))
We still have irb_commandname. When input starts with existing local variable and command name, it is possible to show a navigation message for it.

irb> help = 1
=> 1
irb> help + 1
If you want to use help command, try irb_help instead
=> 2

@st0012
Copy link
Member

st0012 commented May 28, 2024

especially when using chws or rdbg command

That's a good point 🤔

And I think the behavior is complex/hard to understand for user.

I personally don't think that'd be the case as they are the ones who define the local variables.

How about simply make the precedence:

Then we'll need to change that for irb:rdbg session together too. Otherwise the behaviour will be inconsistent:

$ ruby test.rb 

From: test.rb @ line 3 :

    1: help = 1
    2: 
 => 3: binding.irb

irb(main):001> help
=> 1
irb(main):002> debug
irb:rdbg(main):003> help

### Control flow

* `s[tep]`
  * Step in. Resume the program until next breakable point.
* `s[tep] <n>`
  * Step in, resume the program at `<n>`th breakable point.

@tompng
Copy link
Member

tompng commented Jun 29, 2024

Less inconsistency is better, but I think it will be an enhancement even if there is an inconsistency.
We can change how ruby/debug handles command later.

@MatzFan
Copy link

MatzFan commented Sep 20, 2024

Just FYI I suspect I'm seeing this bug by following the usage example of the Rouge gem in IRB:

require 'rouge'
=> true
source = File.read('README.md')

This results in

(eval at /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/command/internal_helpers.rb:22):1:in `<top (required)>': undefined method `extract_ruby_args=' for module IRB::Command (NoMethodError)

IRB::Command.extract_ruby_args = File.read('README.md')
            ^^^^^^^^^^^^^^^^^^^^
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/command/internal_helpers.rb:22:in `eval'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/command/internal_helpers.rb:22:in `block in ruby_args'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/command/internal_helpers.rb:21:in `catch'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/command/internal_helpers.rb:21:in `ruby_args'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/command/load.rb:79:in `execute'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/command/base.rb:42:in `execute'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb/context.rb:603:in `evaluate'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1049:in `block (2 levels) in eval_input'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1380:in `signal_status'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1041:in `block in eval_input'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1120:in `block in each_top_level_statement'
	from <internal:kernel>:187:in `loop'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1117:in `each_top_level_statement'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1040:in `eval_input'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1021:in `block in run'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1020:in `catch'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:1020:in `run'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/3.3.0/irb.rb:904:in `start'
	from /home/me/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/irb-1.13.1/exe/irb:9:in `<top (required)>'
	from /home/me/.rbenv/versions/3.3.5/bin/irb:25:in `load'
	from /home/me/.rbenv/versions/3.3.5/bin/irb:25:in `<main>'
Maybe IRB bug!

Assigning to a var not named "source" fixes the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

5 participants