ruby 1.8 undefined method `instance_variable_defined?' - ruby

I have been working on my Ruby. When trying to execute this simple example from the Ruby Object documentation, I get this error:
undefined method `instance_variable_defined?'
This is my code:
class Fred
def initialize(p1, p2)
#a, #b = p1, p2
end
end
fred = Fred.new('cat', 99)
fred.instance_variable_defined?(:#a) #=> true
fred.instance_variable_defined?("#b") #=> true
fred.instance_variable_defined?("#c") #=> false
What have I done wrong? I tested this on another machine with Ubuntu 10.04 and it works fine. I'm using Centos 5.5 by the way.
Does anyone knows how to fix this?

The only thing I can think of is that you're using an ancient version of Ruby (1.8.5 or earlier), as Object#instance_variable_defined? has been in Ruby since 1.8.6.

Related

Ruby NoMethodError exception calls #inspect by default

I have found a weird problem in Ruby and I'm not quite sure if it is an issue or it's a feature introduced in recent Ruby versions.
Basically when we call an undefined method, we get an undefined method error as expected in Ruby. The issue is that it also calls inspect and prints out the object and all of its attributes/values. If my object is a complex one, it takes really long time to finish printing everything out and in many times it causes my local rails server to hang, especially when there is an attribute holding binary data. This issue does not seem to happen with Ruby 2.6 but Ruby >= 2.7.
For simple objects, that's not a problem but I'm specifically having the issue with this gem: puppeteer-ruby. Each object in this gem has lots of attributes and dependencies.
Here is an example, I run the following code in IRB with different Ruby version and getting different exceptions:
require 'puppeteer-ruby'
browser = Puppeteer.launch(headless: true)
browser.foo
Ruby 2.6.6
NoMethodError: undefined method `foo' for #<Puppeteer::Browser:0x00007fce2d553b30>
Did you mean? for
Ruby 3.0.0
(irb):9:in `<main>': undefined method `foo' for #<Puppeteer::Browser:0x00007f9300550740 #ignore_https_errors=false, #default_viewport=#<Puppeteer::Viewport:0x00007f92ffbf8e90 #width=800, #height=600, #device_scale_factor=1.0, #is_mobile=false, #has_touch=false, #is_landscape=false>, #process=#<Puppeteer::BrowserRunner::BrowserProcess:0x00007f92fc5ae448 #spawnargs=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "--disable-background-networking", "--enable-features=NetworkService,NetworkServiceInProcess", "--disable-background-timer-throttling", "--disable-backgrounding-occluded-windows", "--disable-breakpad", "--disable-client-side-phishing-detection", "--disable-component-extensions-with-background-pages", "--disable-default-apps", "--disable-dev-shm-usage", "--disable-extensions", "--disable-features=Translate", "--disable-hang-monitor", "--disable-ipc-flooding-protection", "--disable-popup-blocking", "--disable-prompt-on-repost", "--disable-renderer-backgrounding", "--disable-sync", "--force-color-profile=srgb", "--metrics-recording-only", "--no-first-run", "--enable-automation", "--password-store=basic", "--use-mock-keychain", "--enable-blink-features=IdleDetection", "--headless", "--hide-scrollbars", "--mute-audio", "about:blank", "--remote-debugging-port=0", "--user-data-dir=/var/folders/qn/kx4kb8xx5x13gx77yy2q56fr0000gn/T/puppeteer_dev_chrome_profile-20210910-25051-m7mnxb"], #stdout=#<IO:fd 24>, #stderr=#<IO:fd 26>,......very long text after this..
Thats interesting - inspect has always printed internal variables.
In the blame the last change to inspect was 9 years ago: rb_object_inspect#704
A simple script using 2.6:
> docker run -it ruby:2.6.6-alpine sh
#> ruby -v
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-linux-musl]
#> irb
irb(main):001:0> class Foo; def initialize(message); #message = message; end; end
=> :initialize
irb(main):002:0> Foo.new('hello').foo
NoMethodError (undefined method `foo' for #<Foo:0x00007f35e20e0280 #message="hello">)
Did you mean? for
Though looking at the source for Puppeteer::Browser it seems they changed to a pure ruby implementation of the browser around 2 years ago. When they did that they introduced a lot of ivars to the class. Perhaps the version you're using changed between updating ruby from 2.6 to 3.0?
A simple fix would be to monkey patch inspect on Puppeteer::Browser, or send a PR to the maintainer - looks like the project is active on GitHub.

Upgraded to minitest 5.4.0. Now must* and won't* doesn't work within Minitest::Test subclass, but assert* still works

I have been using the MiniTest that comes with Ruby 2.1 without a problem. I would subclass MiniTest::Unit:TestCase create a couple methods like 'test_simple', and everything just worked. I would use Expectations and Asserts without a problem.
I have upgraded Minitest to 5.4.0 using a gem. Everywhere I use Expectations (musts and wonts) I get a strangle error. Example of the test class.
gem 'minitest'
require "minitest/autorun"
require "rest-client"
require "json"
require "pp"
# require './testcase_addins'
class TestUserKey < Minitest::Test
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
When I run this, the assert line passes without a problem, but must_be line throws this error:
1) Error:
TestUserKey#test_simple:
NoMethodError: undefined method `assert_operator' for nil:NilClass
(eval):4:in `must_be'
user_key_testcase.rb:14:in `test_simple'
The strange part is what is the nil:NilClass in the error can't be nil; it's 0. Even I change the Fixnum to a String, I still get the same error.
If I change the test to a spec test, everything works again. So I can't use Expectations with in Unit Tests? IF that is the case, could someone explain why?
The short answer is that with 5.4.0 your test class must inherit from MiniTest::Spec in order to use expectations.
I tested this on a new ubuntu machine with ruby 2.1.2 installed via RVM:
rvm install ruby-2.1.2
This code works with the stock ruby 2.1.2 (no 5.4.0 minitest gem installed, slightly cleaned up from your example code above):
#!/usr/bin/env ruby
require 'minitest/unit'
require "minitest/autorun"
class TestUserKey < MiniTest::Unit::TestCase
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
Running this code works fine. To reproduce the error listed above, install minitest 5.4.0:
gem install minitest -v 5.4.0
Now the code fails with "NoMethodError: undefined method `assert_operator' for nil:NilClass". You now have both versions of minitest installed:
~/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/minitest/ # stock ruby version of minitest
~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/ # minitest v5.4.0 installed via rubygems
Now that everything is set up, we can dig into what exactly is happening. The expectations are defined with a call to infect_an_assertion, like this:
infect_an_assertion :assert_operator, :must_be, :reverse
For 5.4.0 that call happens in ~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/lib/minitest/expectations.rb. It's roughly the same in both versions, it just happens in a different place.
infect_an_assertion is also roughly the same for both versions. For :must_be it winds up making this call, which is identical between the two versions of minitest:
MiniTest::Spec.current.#{meth}(args.first, self, *args[1..-1])
They're doing some metaprogramming here, the call at runtime will look more like this since meth is set to assert_operator:
MiniTest::Spec.current.assert_operator(...)
The important part is MiniTest::Spec.current. In 5.4.0 this method returns nil, which results in a NoMethodError exception when it tries to call assert_operator on nil.
In the stock minitest from ruby 2.1.2:
Here MiniTest::Spec inherits from MiniTest::Unit::TestCase. TestCase defines the method current and returns a value that was set in the initialize method. You can see this all happening around line 1303 of ~/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/minitest/unit.rb:
def initialize name # :nodoc:
#__name__ = name
#__io__ = nil
#passed = nil
##current = self # FIX: make thread local
end
def self.current # :nodoc:
##current # FIX: make thread local
end
Therefore, when you inherit from MiniTest::Unit::TestCase in your test class with the stock minitest, current is defined as a method and is guaranteed to return a value when the above call to MiniTest::Spec.current is made. This is why it works in the stock ruby 2.1.2 minitest.
In minitest 5.4.0
In 5.4.0, Minitest::Spec inherits from Minitest::Test, which does not define current (nor do any of its parents). The current method is defined directly on Minitest::Spec. It simply returns Thread.current[:current_spec]:
# line 83 of ~/.rvm/gems/ruby-2.1.2/gems/minitest-5.4.0/lib/minitest/spec.rb
def self.current # :nodoc:
Thread.current[:current_spec]
end
The value of Thread.current[:current_spec] is set in the Minitest::Spec constructor on line 87 of the same file:
def initialize name # :nodoc:
super
Thread.current[:current_spec] = self
end
The problem is that when your test class inherits from Minitest::Test, the Minitest::Spec constructor never gets called and Thread.current[:current_spec] is never initialized. That means the call in infect_an_assertion to Minitest::Spec.current returns nil, which results in the NoMethodError you're seeing when it tries to call assert_operator on nil. The solution is to make your test class inherit from Minitest::Spec so that the constructor is called and Thread.current[:current_spec] gets a value.
Here is a slightly modified version of the original code that works with minitest 5.4.0:
#!/usr/bin/env ruby
gem 'minitest'
require "minitest/autorun"
class TestUserKey < Minitest::Spec
def test_simple
data = 0
assert( data >= 0 )
data.must_be :>=,0
end
end
Hope this helps!
From the minitest readme, it seems like the must style syntax is a part of the spec syntax, which would require you to use methods like describe and it instead of defining your own unit test methods.

Rails 4 Engine: Method on Eigenclass of Module not found

I have updated my mountable engine from Ruby 1.9.3 / Rails 3.2 to Ruby 2.0.0 / Rails 4. Now I am having a strange problem with my namespaced models. It can't find the correct table name. I've figured that the reason for this is a problem with the tabele_name_prefix method on the parent module. It can't be found.
module DynaState::AttributeAccessors
def self.table_name_prefix
'dyna_state_attribute_accessors_'
end
def self.foo
'bar'
end
end
If I test this in the rails console:
2.0.0p0 :004 > DynaState::AttributeAccessors.table_name_prefix
NoMethodError: undefined method `table_name_prefix' for DynaState::AttributeAccessors:Module
2.0.0p0 :005 > DynaState::AttributeAccessors.foo
NoMethodError: undefined method `foo' for DynaState::AttributeAccessors:Module
Whereas when I define it on the fly in the console:
2.0.0p0 :002 > module Foo; def self.bar; 'argh!' end; end;
2.0.0p0 :003 > Foo.bar
=> "argh!"
My guess is that during initialization it is not evaluating all the files that compose the module. Especially not the file where the methods are defined. But I don't know how to fix it or if it is even the problem.
Do you have any Idea how I could debug this or what the problem is?
EDIT: This problem is only occuring with the ONE module. The AttributeAccessors module.
You cannot call methods on a Module until you've included or extended them in a class, if in your console you do
extend DynaState::AttributeAccessors
and then
DynaState::AttributeAccessors.table_name_prefix
That should most likely do it for you. I'm really not sure but the module defined on the fly in the console might be available/included in the main scope of the console context.

ruby 2.0 undefined method ObjectSpace.trace_object_allocations

tried this on ruby 2.0.0 / 247 or head:
require 'objspace'
ObjectSpace.trace_object_allocations -> undefined method `trace_object_allocations'
for ObjectSpace:Module
Docs say it should work http://www.ruby-doc.org/stdlib-2.0/libdoc/objspace/rdoc/ObjectSpace.html any idea what I'm missing ?
For higher ruby versions you still may get errors like:
undefined method `memsize_of' for ObjectSpace:Module
To solve this issue -> You need to require 'objspace'. According to https://ruby-doc.org/stdlib-2.3.1/libdoc/objspace/rdoc/ObjectSpace.html#method-c-memsize_of
Only available when installing ruby-head aka ruby 2.1
From the output of puts ObjectSpace.methods.sort after requiring objspace, it looks like that method doesn't exist.
irb(main):005:0> puts ObjectSpace.methods.sort
...
reachable_objects_from
remove_class_variable
remove_instance_variable
respond_to?
send
singleton_class
singleton_methods
taint
tainted?
tap
to_enum
to_s
trust
undefine_finalizer
untaint
untrust
untrusted?
=> nil
irb(main):009:0> ObjectSpace.methods.include? :trace_object_allocations
=> false
You can see that it contains the ::reachable_objects_from method, which is mentioned in the docs, but not the one you're looking for, unfortunately.

Ruby 2.0 throws "[BUG] Stack consistency error"

I'm following the exercises from Ruby Koans and in about_proxy_object_project.rb there's this bit of code:
class Proxy
def initialize(target_object)
#object = target_object
end
# This method was added by me
def method_missing(method_name, *args, &block)
#object.send method_name
end
end
That gets called like this:
def test_tv_methods_still_perform_their_function
tv = Proxy.new(Television.new) # Television is a class with a :channel attr_accessor and a power method
tv.channel = 10
tv.power
assert_equal 10, tv.channel
assert tv.on?
end
The problem is that the line tv.channel = 10 is "breaking" the interpreter and throwing:
[BUG] Stack consistency error (sp: 53, bp: 54)
ruby 2.0.0p0
(...)
full stack trace follows
I've tried the same code with Ruby 1.9.3 and it's working. I'm using Ruby 2.0.0-p195.
So, is this an error/bug? Or I'm doing something horribly wrong?
Yes. It is a Ruby bug in ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-linux]. At the end of the stack trace, it says:
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html
You should report this to Ruby core. Please do so for the sake of the Ruby community.
As pointed out by matt, it is fixed in Ruby 2.0.0p247.
I don't see you doing anything wrong.

Resources