Ruby and .irbrc : Find whether a method is defined. - ruby

I have a function in my .irbrc which basically builds together a string form certain input parameters, and then is supposed to check, whether another function with name of this string exists. I'm doing it like this
methodname = ... # Calculate a string
if respond_to?(methodname)
....
end
This does not work in that respond_to? returns false even in those cases where in my opinion it should return true. I have boiled down the problem to the following simple case:
I have in my .irbrc
def foo
end
def respond_to_foo?
respond_to?(:foo)
end
puts "Respond: #{respond_to_foo?}"
Running irb, this outputs false. I would expect it to print true instead. Still, I am able to run foo from within irb.
I guess that this has to do with the scope in which irb defines my methods. For instance, self.foo does not work (private method 'foo' called for main:Object), while send.foo does work (since it bypasses privacy). This looks like a clue to my problem, but I still can't come up with an explanation, nor find the proper way for doing my task.
Could someone enlighten me?

To answer my own question: It just occured to me, that I could use
private_methods.include?(:foo)
This does work, but it looks a bit like a hack to me. If someone knows a better way, please let me know.

Related

what is a variable/object/thing starting with a # in ruby

I am new to Ruby, so go easy :).
Anyway, I am trying to work out some stuff in the chef-provisioning-aws gem. One thing in particular is that there is an object called:
new_resource.driver.ec2_client
When I do an inspect on that object it returns exactly this:
#<Aws::EC2::Client>
So, my question is: what is this? What sort of "thing" in Ruby starts with a pound sign (hash) and has <...> in it?
Much appreciated.
The output of Ruby's inspect method is roughly like this unless you override it:
"#<#{self.class}:0x#{self.object_id.to_s(16)}"
So in other words: "#<ClassName:0xobject_id in hex>".
class Foo ; end
Foo.new.inspect
#=> "#<Foo:0x007ffe0eeea520>"
It seems that for Aws::EC2::Client it was overriden and does not include the object id.
It's the default implementation of the inspect method (although then the object ID should be included). It may be useful in some situations to implement your own method, so you can get an instant overview of what you want to know about this object. The # is just a random character and has no further meaning here.

Is there no convenience method for !nil?

I think I would see my code better if I would ask myself object.not_nil? vs !object.nil?. So my question: Is there really no convenience method for !nil? to sugar things up? Is it in front of my eyes and I cannot see it or am I just missing an important point?
How about this?
not object.nil?
But the easier thing to do would be to check for the "truthiness" of by testing the variable itself. Since nil is implicitly false you can just check object.
You can introduce the sugar at an upper level. Instead of:
if not object.nil?
you can write:
unless object.nil?
What about this ?
if object
# sth
end
It is not the same as it will not be executed if object is false but depending on you code, it could be better.
Another solution (which is not the same either), as you tagged your question with ruby-on-rails-3 : using present? which will not execute the block for [] or {} unlike !object.nil?.
Again another one depending of the case : using unless which won't be really nice if your condition is more complex (with && and/or ||).
If your condition is of this form :
if !object.nil? && object.something?
# sth
end
You can use try, as you are using Rails, like this :
if object.try(:something?)
# sth
end
In all the other cases, !object.nil? or not object.nil? stays the best solution I guess.
When convenience around #nil? is discussed, Activesupport's methods #blank? and #present? shouldn't be forgotten either.
Not that you'd necessarily want to, but you can introduce not_nil? yourself:
class Object
def not_nil?
!self.nil?
end
end
then you can do things like:
nil.not_nil?
==> false
3.not_nil?
==> true
a = []
a.not_nil?
==> true

How can you find the name of the file that called a method in Ruby?

Is there a nice, recommended way to get the name of the file that called a method? I don't want to pass __FILE__ every time. The closest thing I've found is taking the first element of Kernel.caller, which is okay but has the calling line number appended like "test.rb:7". It's easy enough to strip off, but using it seems like something that might be dependent on the interpreter or might change in the future.
In Ruby 2.0+ you can do this using Kernel#caller_locations. It's very similar to caller, with the added benefit that you don't need to parse out the file name manually, since it returns Thread::Backtrace::Location objects instead of Strings:
file1.rb:
def some_method
puts caller_locations.first.path
end
file2.rb:
require_relative './file1'
some_method
Shell:
$ ruby file2.rb
file2.rb
Perhaps it's safer than you think? I found this other post http://snippets.dzone.com/posts/show/2787 where someone did something similar to what you're suggesting...

When does Ruby know that a method exists?

One question that ran through my mind was how does the Ruby interpreter know that a method exists on a object if the definition is yet to be interpreted? Like, wouldn't it matter whether you define the method first than use it, rather than use it then define it?
It doesn't know, and it doesn't care - until execution. When a method call statement is executed, the interpreter looks to see if the class (object, not code!) has the named function. If it does not, it looks up the ancestor tree. If it does not find any, it calls the method_missing method. If that is not defined, you get your error.
If your function call does not get executed, you will not get any errors.
The interpreter doesn't know about undefined methods ahead of time, for example:
o = Object.new
o.foo # => Raises NoMethodError.
class Object
def foo
puts "Foo!"
end
end
o.foo # => prints "Foo!", since the method is defined.
However, Ruby has a neat feature called method_missing which let's the receiver of a method call take the method name and arguments as separate arguments and handle accordingly as long as no defined method already handles the call.
def o.method_missing(sym, *args)
puts "OK: #{sym}(#{args.inspect})"
# Do something depending on the value of 'sym' and args...
end
o.bar(1, 2, 3) #=> OK: bar(1, 2, 3)
"Method missing" is used by things like active record find methods and other places where it could make sense to have "dynamically defined" functions.
The problem is, the interpreter tried to find it when you use it, and since it won't be there, it may fail.
In ( some ) compiled languages, it doesn't matter, because while compiling, the compiler may say "I'll look for this on a second pass" but I don't think this is the case with Ruby.

Ruby Koan: test_nil_is_an_object

I have recently tried sharpening my rails skills with this tool:
http://github.com/edgecase/ruby_koans
but I am having trouble passing some tests. Also I am not sure if I'm doing some things correctly since the objective is just to pass the test, there are a lot of ways in passing it and I may be doing something that isn't up to standards.
Is there a way to confirm if I'm doing things right?
a specific example:
in about_nil,
def test_nil_is_an_object
assert_equal __, nil.is_a?(Object), "Unlike NULL in other languages"
end
so is it telling me to check if that second clause is equal to an object(so i can say nil is an object) or just put assert_equal true, nil.is_a?(Object) because the statement is true?
and the next test:
def test_you_dont_get_null_pointer_errors_when_calling_methods_on_nil
# What happens when you call a method that doesn't exist. The
# following begin/rescue/end code block captures the exception and
# make some assertions about it.
begin
nil.some_method_nil_doesnt_know_about
rescue Exception => ex
# What exception has been caught?
assert_equal __, ex.class
# What message was attached to the exception?
# (HINT: replace __ with part of the error message.)
assert_match(/__/, ex.message)
end
end
Im guessing I should put a "No method error" string in the assert_match, but what about the assert_equal?
assert_equal true, nil.is_a?(Object) is indeed the correct solution. The question is "Are nils in Ruby objects or not?", and in Ruby's case, they are. Thus, in order to pass the assertion, you should assert the truth of that test.
In the second example, when you call an undefined method on nil, you get NoMethodError: undefined method 'foo' for nil:NilClass. Thus, the exception class is NoMethodError, and the message is undefined method 'foo' for nil:NilClass. Test the failing behavior in a console, and see what you get from it, and then apply that knowledge to the test.
Are you running
ruby path_to_enlightenment.rb
at the command prompt after you correct each test? It will give you lots of help.
Also "remember that silence is sometimes the best answer" -- if you are stumped don't put in anything and the tool will help you.
Well, in holding with the typical TDD motto of Red-Green-Refactor, you should run the test (probably with rake in a separate console) and see the failure happen. From there, they have provided you a few pieces of information about what was expected.
As for style, the koans aren't really teaching that. You should just find and read some code written in ruby to get a feel for the typical conventions and idioms of the ruby community.
Simplicity is the key with Ruby Koans - when I started it I thought it must be harder than what it is, but it's not! Just ask IRB the question Koans is asking you, and after a few you get a feel for it. I've written a blog piece about it to help others, too:
Ruby Koans Answers
I remember when I did this that I tried to out think the test and tried to put in
<Answer> and <"Answer">
The thing to remember is that the actual class doesn't have to be in a string or something.
So the answer is NOT
ex.class, ex.class
As suggested above, put the code into irb and execute it.
(1..5).class == Range
is a big hint

Resources