Figure out where a method was defined - ruby

If I follow the following part of this article:
Figure out where a method was defined
object = Object.new
puts object.method(:blank?).source_location
=> ["/gems/activesupport-5.0.0.beta1/lib/active_support/core_ext/object/blank.rb", 14]
I should be able to find the definition of the blank? method, however when I try this code within irb with ruby 2.0.0 I get this error message:
➜ ~ irb
irb(main):001:0> object = Object.new
=> #<Object:0x007fc84882f088>
irb(main):002:0> puts object.method(:blank?).source_location
NameError: undefined method `blank?' for class `Object'
from (irb):2:in `method'
from (irb):2
from /usr/bin/irb:12:in `<main>'
Did I miss anything?
Thank you.

.blank? method does not exist for a Object type. I know for sure it exists for a String method if I include the active_support lib
irb(main):001:0> String.new.method(:blank?).source_location
=> ["/home/xeon/.rbenv/versions/2.3.4/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/core_ext/object/blank.rb", 116]
If you include activesupport-5.0.0.beta1 then it will work for you. (Looking at the source path of the article you have posted)

Related

Why is RSpec giving a NoMethodError when method exists?

I'm getting the error below
$ bundle exec rspec calculatorcli_spec.rb
Failure/Error: c = CalculatorCLI.parse
NoMethodError:
undefined method `parse' for CalculatorCLI:Class
from the below simple calculator class
CalculatorCLI is a class, and you're missing its initialization
either change CalculatorCLI.parse to CalculatorCLI.new.parseor changedef parsetodef self.parseinCalculatorCLI` definition

Ruby: how to determine an object type in irb and binding.pry?

I have just begun adding binding.pry after my objects in order to start determining what they evaluate to. However, now I want to know what type of object the output is.
How can I do this in irb? How can I do this in binding.pry?
EDIT:
Here is what I have tried to determine the type of object H. I know it is a hash, but sometimes it is less obvious in the console:
irb(main):001:0> H = Hash["a" => 100, "b" => 200]
=> {"a"=>100, "b"=>200}
irb(main):002:0> H
=> {"a"=>100, "b"=>200}
irb(main):003:0> type(H)
NoMethodError: undefined method `type' for main:Object
from (irb):3
from /Users/macbook/.rbenv/versions/2.3.0/bin/irb:11:in `<main>'
irb(main):004:0> object.class(H)
NameError: undefined local variable or method `object' for main:Object
Did you mean? object_id
from (irb):4
from /Users/macbook/.rbenv/versions/2.3.0/bin/irb:11:in `<main>'
irb(main):005:0> object.is_a?(H)
NameError: undefined local variable or method `object' for main:Object
Did you mean? object_id
from (irb):5
from /Users/macbook/.rbenv/versions/2.3.0/bin/irb:11:in `<main>'
You can get the class with
h = {a: 100, b: 200}
h.class
# Hash
You can also check if something is of a particular class
h.is_a? Hash
# true
h.is_a? String
# false
The Ruby Language has no concept of "type". Or, to be more precise: in Ruby, types only exist latently in the mind of the programmer, they are not manifest in the program. Ergo, there is no way to get an object's type from the program, you can only get it from the programmer.
Sometimes, types are written down in the documentation or in comments. Some types are basically community folklore, not written down anywhere but passed down from generation to generation.
You can ask an object about its class, you can ask it about its methods, you can ask it whether it responds to a specific message, but you can not ask it about its type.
Note that older versions of Ruby had a type but that method was removed because it was misleading: it didn't actually return the type (I explained above why that is impossible), it returned the class, which is something completely different.

Parent class's instance variable in Ruby

So, for whatever reason there is no peek method in the ruby core Queue class. I am trying to create a child class that implements the peek method. However, I don't understand why I am getting an error. Is it not possible to use instance variables in this way? Looking at the source code for Queue, there are instance variables in the constructor of the parent class. Is there a way to reference these in the subclass?
class PeekQueue < Queue
def peek
#mutex.synchronize{
while true
if #que.empty?
raise ThreadError, "queue empty" if non_block
#waiting.push Thread.current
#mutex.sleep
else
return #que[0]
end
end
}
end
end
a = PeekQueue.new
a.push(1)
a.peek
NoMethodError: undefined method 'synchronize' for nil:NilClass
Edit: The Queue class is created at compile time, which is why I couldn't find the source on the ruby source code on github. This is what the parent class looks like:
https://gist.github.com/anonymous/574e20fea3a28663bfe2
I do not see that error:
irb(main):025:0> qq = PeekQueue.new
=> #<PeekQueue:0x000006002bf498 #que=[], #num_waiting=0, #mutex=#<Mutex:0x000006002bf420>, #cond=#<ConditionVariable:0x000006002bf3f8 #waiters={}, #waiters_mutex=#<Mutex:0x000006002bf3a8>>>
irb(main):026:0> qq.peek
NameError: undefined local variable or method `non_block' for #<PeekQueue:0x000006002bf498>
from (irb):15:in `block in peek'
from (irb):12:in `synchronize'
from (irb):12:in `peek'
from (irb):26
from /usr/bin/irb:12:in `<main>'
irb(main):027:0> qq.push 1
=> #<ConditionVariable:0x000006002bf3f8 #waiters={}, #waiters_mutex=#<Mutex:0x000006002bf3a8>>
irb(main):028:0> qq.peek
=> 1
Method #non_block seems to be an issue. But access to #mutex works with your code.

Ruby. Crack gem. -- in `<main>': undefined method `[]' for nil:NilClass (NoMethodError) --

Dear stackoverflow community,
Beginner's question:
Why do I get the following error?
scraper_sample_2.rb:7:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
>Exit code: 1
Here's my code (copied from a ruby's intro guide):
require "rubygems"
require "crack"
require "open-uri"
URL = "http://www.recovery.gov/pages/GetXmlData.aspx?data=recipientHomeMap"
Crack::XML.parse(open(URL).read)["totals"]["state"].each do |state|
puts ["id", "awarded", "received", "jobs"].map{|f| state[f]}.join(",")
end
Because Crack::XML.parse(open(URL).read)["totals"] is nil. Try to split the call you do on line 7 on several lines and debug each call separately. Maybe the answer you get is not what you expect.
Given the format of the xml returned from your source, Crack::XML.parse(open(URL).read)["totals"] will, as Ivaylo said, return nil. The format of the xml must have changed, as totals are now within /map/view.
To get the expected output, change your code to:
Crack::XML.parse(open(URL).read)["map"]["view"]["totals"]["state"].each do |state|
puts ["id", "awarded", "received", "jobs"].map{|f| state[f]}.join(",")
end

Array.find method problem

I find this line in the ZenTest source code:
result = #test_mappings.find { |file_re, ignored| filename =~ file_re }
The #test_mappings and result here are both Array object, but I didn't found 'find' method on Array class in ruby doc. I also tried it on irb:
irb(main):014:0> Array.respond_to? :find
=> false
irb(main):015:0> [1,2,3].find
LocalJumpError: no block given
from (irb):15:in `find'
from (irb):15:in `each'
from (irb):15:in `find'
from (irb):15
irb(main):016:0> [1,2,3].find{|x| x>1}
=> 2
Could any one explain it to me? How could find method also return an Array object? thanks in advance.
Array includes the Enumerable module, which adds the find method.
In your example you tested Array.respond_to. This will only return true for class methods of Array. find is an instance method, so respond_to? must be invoked on an instance of the class.
>> a = Array.new
=> []
>> a.respond_to? :find
=> true
Another sometimes useful trick is calling the 'methods' function which lists all the methods available to the instance of the object and using the grep method to filter out for something specific. It also gives you a good picture of what standard methods are provided by base classes without referring to docs.
a = Array.new
=> []
>> a.methods.grep /find/
=> ["find", "find_all"]

Resources