Why am I getting NoMethodError from IRB for my own Module and method - ruby

I have taken this example exactly from the Ruby Cookbook. Unfortunately for me, like a whole lot of the examples in that book, this one does not work:
my file (Find.rb - saved both locally and to Ruby\bin):
require 'find'
module Find
def match(*paths)
matched=[]
find(*paths) { |path| matched << path if yield path }
return matched
end
module_function :match
end
I try to call it this way from IRB, according to the example the book provides:
irb(main):002:0> require 'Find'
=> false
irb(main):003:0> Find.match("./") { |p| ext = p[-4...p.size]; ext && ext.downcase == "mp3" }
It SHOULD return a list of mp3 files in my recursive directory. Instead, it does this:
NoMethodError: undefined method `match' for Find:Module
from (irb):3
from C:/Ruby192/bin/irb:12:in `<main>'
What gives? I'm new at this (although I MUST say that I'm farther along with Python, and much better at it!).
How can I get IRB to use my method?

I ran into this with irb on a Mac running Snow Leopard while using the default version of ruby (and irb of course) installed with OS X. I was able to get past it by including the module in IRB after loading the module or in the file after the module definition.
include module_name
I'm not sure if this is a defect or known behavior.

The only explanation is that the code you posted is not the code you are running, since both carefully reading it and simply cut&paste&running it shows absolutely no problems whatsoever.

What directory are you calling IRB from? Try calling it from the directory where your find.rb file is located. Also, I don't know if it makes any difference but convention is to name the file the lowercase version of the module / class. So the module would be Find and the file name would be find.rb. You shouldn't need the require call in the file itself.
So, start your command prompt window, cd into the directory that contains find.rb and run irb. In IRB you should be able to require "find" and it should return true. From there you should be able to call Find.match.

I know this question is already 3 years old, but since this is the first hit on google for the problem, and I had been banging my head against the wall all afternoon with the same problem doing the tutorial here: http://ruby.learncodethehardway.org/book/ex25.html, here goes: the function definition in the module should read
module Find
def Find.match(*paths)
...
end
end

Related

Find path to file that required this one

I'll show an example of what I'm trying to do.
child.rb
require 'parent'
class Child < Parent
...
end
parent.rb
class Parent
puts __FILE__
...
end
running this (e.g. in IRB):
require 'child'
child=Child.new
returns this:
/path/to/parent.rb
but i'm really trying to get the file child.rb instead.
How can i do this without moving the puts __FILE__ in to the child class directly?
There is no way in Ruby to get what you are asking for. Perhaps if you explained why you want this—what you are trying to accomplish—then I (or someone else) could help you further. As it stands you seem to be asking an XY problem.
Although it's not always the "file that required me", you can use $0 in this case instead of __FILE__ to get "the root file that is running" in the case when you have done ruby parent.rb. Note that this will not work with IRB, however. (Inside IRB $0 is always "irb" or something equally unhelpful.)
Redefine require to output caller_locations.first.absolute_path before calling the original require.
you can use some backtrace method like caller_locations(1,1)[0].path or caller

How to execute local functions using code from external file in ruby?

Can a require execute a locally defined function? I guess the easiest way to describe what I need is to show an example.
I'm using ruby 1.9.3, but solutions for 1.8 and 2.0 are also welcome.
I have a file main.rb as the following:
class Stuff
def self.do_stuff(x)
puts x
end
require_relative('./custom.rb')
do_stuff("y")
end
And also have a file custom.rb in the same folder, with the following content:
do_stuff("x")
Running main.rb, I have following output:
/home/fotanus/custom.rb:1:in `<top (required)>': undefined method `do_stuff' for main:Object (NoMethodError)
from main.rb:5:in `require_relative'
from main.rb:5:in `<class:Stuff>'
from main.rb:1:in `<main>'
Note that without the require, the output is y.
I'm not sure if it is the best solution but using eval should do the trick.
class Stuff
def self.do_stuff(x)
puts x
end
eval(File.read('./custom.rb'))
do_stuff("y")
end
The output will be:
pigueiras#pigueiras$ ruby stuff.rb
x
y
In C, #include literally drops the code as-is into the file. require in Ruby is different: it actually runs the code in the required file in its own scope. This is good, since otherwise we could break required code by redefining things before the require.
If you want to read in the contents of a script and evaluate it in the current context, there are methods for doing just that: File.read and eval.

Is there a "main" method in Ruby like in C?

I'm new to Ruby, so apologies if this sounds really silly.
I can't seem to figure out how to write a "main" code and have methods in the same file (similar to C). I end up with a "main" file which loads a seperate file that has all the methods. I appreciate any guidance on this.
I spotted the following SO post but I don't understand it:
Should I define a main method in my ruby scripts?
While it's not a big deal, it's just easier being able to see all the relevant code in the same file. Thank you.
[-EDIT-]
Thanks to everyone who responded - turns out you just need to define all the methods above the code. An example is below:
def callTest1
puts "in test 1"
end
def callTest2
puts "in test 2"
end
callTest1
callTest2
I think this makes sense as Ruby needs to know all methods beforehand. This is unlike C where there is a header file which clearly list the available functions and therefore, can define them beneath the main() function
Again, thanks to everyone who responded.
#Hauleth's answer is correct: there is no main method or structure in Ruby. I just want to provide a slightly different view here along with some explanation.
When you execute ruby somefile.rb, Ruby executes all of the code in somefile.rb. So if you have a very small project and want it to be self-contained in a single file, there's absolutely nothing wrong with doing something like this:
# somefile.rb
class MyClass
def say_hello
puts "Hello World"
end
end
def another_hello
puts "Hello World (from a method)"
end
c = MyClass.new
c.say_hello
another_hello
It's not that the first two blocks aren't executed, it's just that you don't see the effects until you actually use the corresponding class/method.
The if __FILE__ == $0 bit is just a way to block off code that you only want to run if this file is being run directly from the command line. __FILE__
is the name of the current file, $0 is the command that was executed by the shell (though it's smart enough to drop the ruby), so comparing the two tells you precisely that: is this the file that was executed from the command line? This is sometimes done by coders who want to define a class/module in a file and also provide a command-line utility that uses it. IMHO that's not very good project structure, but just like anything there are use cases where doing it makes perfect sense.
If you want to be able to execute your code directly, you can add a shebang line
#!/usr/bin/env ruby
# rest of somefile.rb
and make it executable with chmod +x somefile.rb (optionally rename it without the .rb extension). This doesn't really change your situation. The if __FILE__ == $0 still works and still probably isn't necessary.
Edit
As #steenslag correctly points out, the top-level scope in Ruby is an Object called main. It has slightly funky behavior, though:
irb
>> self
=> main
>> self.class
=> Object
>> main
NameError: undefined local variable or method `main' for main:Object
from (irb):8
Don't worry about this until you start to dig much deeper into the language. If you do want to learn lots more about this kind of stuff, Metaprogramming Ruby is a great read :)
No there isn't such structure. Of course you can define main function but it won't be called until you do so. Ruby execute line by line so if you want to print 'Hello World' you simply write:
puts 'Hello World'
The question that you mentioned is about using one file as module and executable, so if you write
if __FILE__ == $0
# your code
end
It will be called only if you run this file. If you only require it in other file then this code will never run. But IMHO it's bad idea, better option is using RubyGems and there add executables.
Actually there is a main, but it is not a method; it's the top-level object that is the initial execution context of a Ruby program.
class Foo
p self
end
#=> Foo
p self
#=> main
def foo
p self
end
foo
#=> main
There is no magic main function in Ruby. See http://en.wikipedia.org/wiki/Main_function#Ruby
If you wish to run Ruby scripts like C compiled files, do the following:
#!/usr/bin/env ruby
puts "Hello"
and then chmod a+x file_name.rb. Everything that is below the first line will be run, as if it was contents of main in C. Of course class and function definitions won't give you any results until they are instantiated/invoked (although the code inside class definitions is actually evaluated, so you could get some output but this is not expected in normal circumstances).
Another way to write main() method is:
class HelloWorld
def initialize(name)
#name = name
end
def sayHello()
print "Hello ##name!"
end
end
def main()
helloWorld = HelloWorld.new("Alice")
helloWorld.sayHello
end
main

Ruby koans triangle.rb require error

I'm doing the Ruby Koans tutorial, using notepad++.
The about_triangle_project.rb can't seem to load the triangle.rb file.
no such file to load -- triangle.rb <LoadError>
from <internal:lib/rubygems/custom_require>:29:in 'require'
from about_triangle_project.rb:4: in '<main>'
However I don't think I've altered the files. (I tried to fix it but always undid these when they didn't work)...
Here's the code in about_triangle_project.rb
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
require 'triangle.rb' # this is line 4
class AboutTriangleProject < EdgeCase::Koan
def test_equilateral_triangles_have_equal_sides
assert_equal :equilateral, triangle(2, 2, 2)
assert_equal :equilateral, triangle(10, 10, 10)
end
(etc)
I have tried require 'triangle', that didn't work.
I tried using an absolute pathname, that didn't work.
and the triangle.rb file is in the same directory, unaltered, with comments and just this:
def triangle(a,b,c)
end
class TriangleError < StandardError
end
The triangle.rb file does exist in the same directory, so why can't it be found?
I hope I'm not missing something glaringly obvious!
It appears that on Windows, adding the current directory to the load path doesn't quite work right. Substituting require 'triangle.rb' for require_relative 'triangle.rb' should work, but is a bit of a hack. I don't use Windows, so I'm not sure what the proper solution would be.
I'd definitely look into obtaining a version of Sublime Text Editor, it makes things much cleaner and you can actually open folders in it.
And it looks like your pathing is wrong, I would say make sure that the address of triangle.rb is correct in your code.
Mine looks something more like this
require File.expand_path(File.dirname(FILE) + '/neo')
#You need to write the triangle method in the file 'triangle.rb'
require './triangle'
I'm learning ruby with the Koans right now and found this issue too.
So what was happening to us is that the current working directory (cwd) where the code is ran from affects ruby's require method. You will need to change where the cwd is to the folder of all the koans with cd .\.ruby\koans\ for example. Or, as Ben Langfeld answered, require_relative 'triangle' is a good and easy alternative.
For more info, I'd suggest checking out this What is the difference between require_relative and require in Ruby? thread. My takeaway from this was that require is better used for installed gems and libraries while require_relative is better for code written by you.

Finding relative libraries when using symlinks to ruby executables

Imagine you have an executable foo.rb, with libraries bar.rb layed out in the following manner:
<root>/bin/foo.rb
<root>/lib/bar.rb
In the header of foo.rb you place the following require to bring in functionality in bar.rb:
require File.dirname(__FILE__)+"../lib/bar.rb"
This works fine so long as all calls to foo.rb are direct. If you put as say $HOME/project, and symlink foo.rb into $HOME/usr/bin, then __FILE__ resolves to $HOME/usr/bin/foo.rb, and is thus unable to locate bar.rb in relation to the dirname for foo.rb.
I realize that packaging systems such as rubygems fix this by creating a namespace to search for the library, and that it is also possible to adjust the load_path using $: to include $HOME/project/lib, but it seems as if a more simple solution should exist. Has anyone had experience with this problem and found a useful solution or recipe?
I know this is ages old, but I just found this:
require 'pathname'
APP_ROOT = File.join(File.dirname(Pathname.new(__FILE__).realpath),'..')
You can use this function to follow any symlinks and return the full path of the real file:
def follow_link(file)
file = File.expand_path(file)
while File.symlink?(file)
file = File.expand_path(File.readlink(file), File.dirname(file))
end
file
end
puts follow_link(__FILE__)
Probably worth mentioning that + works nicely with Pathname objects and also there is Kernel.Pathname method, so #Burke's original code could be made even shorter:
require 'pathname'
APP_ROOT = Pathname.new(__FILE__).realpath + "../../lib"

Resources