What exception is raised when using + on symbols in Ruby? - ruby

Doing the Ruby Koans, in the file about_symbols at line 88, I'm not sure of the answer.
This is the code:
def test_symbols_cannot_be_concatenated
# Exceptions will be pondered further farther down the path
assert_raise(what should i put?) do
:cats + :dogs
end

The point of the Ruby Koans is to learn by reading and trying things out.
Open up a terminal and start irb. Then try using the + operator on two symbols. Check the error you get and substitute it as appropriate in the Koans file.
Assuming that your prompt ends in $, that will look something like this:
$ irb
irb(main):001:0> :cats + :dogs
The answer you need will be clear pretty quickly in the error that irb spits out.

To go through step by step in case your completely new to Ruby you could try:
Open up a terminal
Type irb at your prompt to get to the interactive ruby prompt
This is where you can quickly try out different Ruby things
Type the command in question :cats + :dogs
Review the output which will look like
NoMethodError: undefined method `+' for :cats:Symbol
from (irb):1
The name of the exception thrown which is what you are looking for is the first thing e.g. NoMethodError

Related

Not able to get result for def using ruby on mac osx

This is just a sample method I have created for testing purpose using Ruby on Mac OSX 10.12 but I don't get the desired output: Can anyone suggest please? I tried getting the result using both paranthesis and without (). It doesn't even throw any error.
def hi
puts "Hello World"
End
hi
hi()
hi("Hello Matz")`
Try this:
def hi
puts "Hello World"
end
hi
hi()
And this:
def greet(greeting)
puts greeting
end
greet("Hello Matz")
Note that in this line:
hi("Hello Matz")`
you have a tick mark at the end, so that is an error:
1.rb:5: syntax error, unexpected tXSTRING_BEG, expecting end-of-input
It doesn't even throw any error.
Then you aren't running that program.
I suggest you open a Terminal window (Applications/Utilities/Terminal.app), and type in:
$ vimtutor
vim is a free computer programming editor that comes with your Mac. Do the tutorial and learn how to use vim. To run a ruby program, you enter your code into a file, then save it as, say, my_prog.rb. Then you need to give that file to ruby to execute it. You execute a ruby program like this:
$ ruby my_prog.rb
You can create a directory for all your ruby programs like this:
$ mkdir ruby_programs
$ cd ruby_programs
To create a new file inside that directory, use vim:
~/ruby_programs$ vi my_prog.rb
Once you are done typing in your code, save the file, which will put you back at the prompt in Terminal, then you can run your program:
~/ruby_programs$ ruby my_prog.rb
Once you get comfortable with vim, and you feel confident running your ruby programs, consider installing macvim with the vivid chalk color scheme:
It's nicer to look at than plain vim.
Try editing your file so that it reads:
def hi
puts "Hello World"
end
hi
Some important differences to note: def and end are both case-sensitive. The inside of the function definition is indented by two spaces. Since the function takes no arguments, no parentheses are necessary on the call to hi on line 4.
Depending on your filename, enter the command ruby FILENAME and you should see the output Hello World
Ruby keywords are case sensitive. Your code uses End and you probably wanted to use end to mark the end of the hi method.
Because End is not the same as end (and End is not a keyword), irb keeps waiting for input and treats the other three lines as part of the hi method. As far as it can tell, its definition is not complete until it reaches the end keyword (all non-capital letters.)
The correct way to define the method is:
def hi
puts "Hello World"
end
Then you can call it using either hi or hi().
Calling it as hi("Hello Matz") (or hi "Hello Matz") throws an ArgumentError exception with the message wrong number of arguments (given 1, expected 0) because it is called with one argument but the definition of method hi doesn't specify anything about arguments (by its definition, the method hi doesn't accept any argument).

Getting an undefined local variable error in Ruby when debugging

I have the following script in a file called foo.rb
def foo(msg)
msg
end
def bar
thing = 123
thing
end
debugger
p foo(:hai)
I run the program in debug mode, like so:
ruby --debug -r debug foo.rb
Notice I make sure the stdlib debug is loaded via -r and I also put the ruby environment into debug mode using --debug
So the first output I get is unexpected:
Debug.rb
Emacs support available.
/Users/M/.rbenv/versions/2.1.2/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:57: RUBYGEMS_ACTIVATION_MONITOR.enter
After that, if I press c to 'continue' the program ends with the following error:
Exception `NameError' at foo.rb:10 - undefined local variable or method `debugger' for main:Object foo.rb:10:in `<main>': undefined local variable or method `debugger' for main:Object (NameError)
Can anyone tell me what I'm doing wrong, and how to actually get debug mode to recognise the relevant debugger command (if that's even the correct command to be using; the docs aren't clear at all on this)
Note: I'm not interested in using 3rd party gems in this instance (e.g. pry or ruby-debug). I'm only interested in understanding how to use the stdlib debugger that comes with Ruby
Update
Since this question was answered, I've gone ahead and created a gist for future reference. For anyone stumbling across this thread you might find it useful: https://gist.github.com/Integralist/5658cb218bb50494a1fa
Don't use -r. The entire mechanism by which an interactive debugging sessions is loaded is by the literal line of code require 'debug'.
Your code should look like this:
def foo(msg)
msg
end
def bar
thing = 123
thing
end
require 'debug'
p foo(:hai)
And you should run the program by simply typing ruby <program_name>.rb.

Trouble with "to" method in RSpec (undefined method)

Completely new to rspec here, as will become evident.
The following rspec file fails:
require_relative( 'spec_helper')
describe GenotypingScenario do
it 'should add genes' do
scen = GenotypingScenario.new
gene = Gene.new( "Pcsk9", 989 )
scen.addGene( gene )
expect( gene.id).to eq( 989 )
ct = scen.genes.count
expect (ct).to equal(1)
expect (5).to eq(5)
end
end
Specifically, the last two expect() lines fail, with errors like this:
NoMethodError: undefined method `to' for 1:Fixnum
Yet the first expect line works fine. And gene.id is definitely a FixNum.
Ruby 2.1.2, rspec 3.0.0, RubyMine on Mac OS 10.9.4.
Any thoughts?
The spacing in your last two expect lines are tripping up the Ruby interpreter.
expect (5).to equal(1)
Is evaluated by Ruby as:
expect(5.to(equal(1)))
When what you really mean is:
expect(5).to(equal(1))
It's the return value from calling expect() that has a method to; RSpec isn't extending the Ruby built-in types. So you should change your last two expectations to read as follows:
expect(ct).to equal(1)
expect(5).to eq(5)
I was following a Rails API tutorial with TDD, when I found a line in the tests that expected a json response not to be empty.
This is how I wrote it:
expect(json).not_to_be_empty
And I got that unfriendly NoMethodError: undefined method 'not_to_be_empty'
I came to the accepted answer on this thread and it opened my eyes.
I then changed the line to:
expect(json).not_to be_empty
I know you could still be looking for the difference, well, welcome to RSpec! I removed the underscore in between not_to and be empty to make two words. It worked like ... good code.

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

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

How do I drop to the IRB prompt from a running script?

Can I drop to an IRB prompt from a running Ruby script?
I want to run a script, but then have it give me an IRB prompt at a point in the program with the current state of the program, but not just by running rdebug and having a breakpoint.
Pry (an IRB alternative) also lets you do this, in fact it was designed from the ground up for exactly this use case :)
It's as easy as putting binding.pry at the point you want to start the session:
require 'pry'
x = 10
binding.pry
And inside the session:
pry(main)> puts x
=> 10
Check out the website: http://pry.github.com
Pry let's you:
drop into a session at any point in your code
view method source code
view method documentation (not using RI so you dont have to pre-generate it)
pop in and out of different contexts
syntax highlighting
gist integration
view and replay history
open editors to edit methods using edit obj.my_method syntax
A tonne more great and original features
you can use ruby-debug to get access to irb
require 'rubygems'
require 'ruby-debug'
x = 23
puts "welcome"
debugger
puts "end"
when program reaches debugger you will get access to irb.
apparently it requires a chunk of code to drop into irb.
Here's the link (seems to work well).
http://jameskilton.com/2009/04/02/embedding-irb-into-your-ruby-application
require 'irb'
module IRB
def self.start_session(binding) # call this method to drop into irb
unless #__initialized
args = ARGV
ARGV.replace(ARGV.dup)
IRB.setup(nil)
ARGV.replace(args)
#__initialized = true
end
workspace = WorkSpace.new(binding)
irb = Irb.new(workspace)
#CONF[:IRB_RC].call(irb.context) if #CONF[:IRB_RC]
#CONF[:MAIN_CONTEXT] = irb.context
catch(:IRB_EXIT) do
irb.eval_input
end
end
end
This feature is available from Ruby 2.4. You can just use binding.irb
E.g.
require 'irb'
a = 10
binding.irb
puts a
If you run above code, you will get irb console, so that you can inspect values of local variables and anything else that is in scope.
Source: http://blog.redpanthers.co/new-binding-irb-introduced-ruby-2-4/
Ruby commit: https://github.com/ruby/ruby/commit/493e48897421d176a8faf0f0820323d79ecdf94a
Just add this line to where you want the breakpoint:
require 'ruby-debug';debugger
but i suggest use pry instead of irb, which is super handy, insert the following line instead:
require 'pry'; binding.pry
I'm quite late to the game but if you're loading a script from within irb/pry already, a simple raise also works to pop you back out to the irb/pry prompt. I use this quite often when writing one off scripts within the rails console.

Resources