Can't list source using debug in ruby 1.8 [duplicate] - ruby

With this minimal ruby code:
require 'debug'
puts
in a file called, e.g. script.rb
if I launch it like so: ruby -rdebug script.rb
and then press l on the debug prompt, I get the listing, as expected
if I instead run it normally as ruby script.rb
when pressing l I get:
(rdb:1) l
[-3, 6] in script.rb
No sourcefile available for script.rb
The error message seems misleading at best: the working directory hasn't changed, and the file is definitely still there!
I'm unable to find documentation on this behavior (I tried it on both jruby and mri, and the behavior is the same)
I know about 'debugger' and 'pry', but they serve a different use case:
I'm used to other scripting languages with a builtin debug module, that can let me put a statement anywhere in the code to drop me in a debug shell, inspect code, variables and such... the advantage of having it builtin it's that it is available everywhere, without having to set up an environment for it, or even when I'm on a machine that's not my own
I could obviously workaround this by always calling the interpreter with -rdebug and manually setting the breakpoint, but I find this more work than the alternative

After looking into the debug source code, I found a workaround and a fix:
the workaround can be:
trace on
next
trace off
list
this will let you get the listing without restarting the interpreter with -rdebug, with the disadvantage that you'll get some otherwise unwanted output from the tracing, and you'll be able to see it only after moving by one statement
for the fix: the problem is that the SCRIPT_LINES__ Hash lacks a value for the current file... apparently it's only set inside tracer.rb
I've changed line 161, and changed the Hash with a subclass that tracks where []= has been called from, and I wasn't able to dig up the actual code that does the work when stepping into a function that comes from a different file
Also: I haven't found a single person yet who actively uses this module (I asked both on #ruby, #jruby and #pry on freenode), and together with the fact that it uses a function that is now obsolete it leads me to be a bit pessimistic about the maintenance state of this module
nonetheless, I submitted a pull request for the fix (it's actually quite dumb and simple, but to do otherwise I'd need a deeper understanding of this module, and possibly to refactor some parts of it... but if this module isn't actively maintaned, I'm not sure that's a good thing to put effort on)

I suspect the Ruby interpreter doesn't have the ability to load the sourcefile without the components in the debug module. So, no -rdebug, no access to the sourcefile. And I agree it is a misleading error. "Debugging features not loaded" might be better.

Related

Make Ruby console execution more verbose

I want to watch the flow the execution of my ruby code when I am in the console. For example, if I have this :
def process
hash = {a:1,b:2}
hash.values.map!{|e| e+1}
end
And I want to see something like this in console when I type process :
hash = {a:1,b:2}
=> {:a=>1, :b=>2}
hash.values.map!{|e| e+1}
=> [2, 3]
Is there a useful way to do something like this?
$VERBOSE doesn't seems to do anything and $DEBUG seems as the opposite to be too verbose.
You're talking about "trace" functionality.
Some languages, like shell and good-ol' GWBasic, have a flag to show their currently executing line. Ruby's $DEBUG output can flood you with information overload, not so much from your code, but from any gems that look for it and dump their current state or turn on their tracing.
Many people sprinkle their code with puts to have it show some indicator of where they are, during their development/testing. If you do that, I'd recommend writing it as a method to bottleneck your output and let you easily turn it on/off. Also, use a flag to check whether you want to debug. You might even want to use OptionParser to let you create a --debug flag to pass on the command-line. Another nice side-effect of using a method is it's easy to redirect the output to a file you can tail and watch the output as it occurs, and later use for triage.
Another alternative is to load the code into the debugger and tell it to trace. You'll see every step of the code, which is very verbose, but the detail is good. You can also tell it to run to certain points so you can poke at the code and dig around, dropping into IRB if needed.
Personally, being old-school and having cut my teeth on assembly-language, I'm comfortable in debuggers, so I use Ruby's a lot. It's easy to tell it to run to a certain spot and stop, or you can embed include 'debugger'; debugger into your code and it'll stop at that point. Once there, it's possible to see what's going on, then c to continue, and let the program run until it hits the debugger statement again. I find the debugger to be very powerful and a nice selective magnifying glass for those times I want to know what's going on.
"Debugging in Ruby" has lots of nice tips you might find useful too.
EDIT:
I like Alex D's suggestion to look into Ruby's set_trace_func. I haven't used it (and, frankly forgot about it), but that'd be a good way to set up a nice trace in an app. With a little code you could set up toggling it on/off and selectively outputting given a certain class or condition since you're in control of the proc being called.
One option would be to use set_trace_func (http://apidock.com/ruby/Kernel/set_trace_func) to set up a hook which will print out each line as it is executed. Be aware that may overwhelm you with a bunch of information on the internals of irb.
Another option would be to dig into the source code for irb and add an option to print each line as it is executed.
Have you tried the pry gem? Put require 'pry'; binding.pry inside your code and run your script. You will have a ruby console just where your put it. Maybe that is what you are looking for.
Otherwise you should take a look at a ruby debugger.

How do I work around Ruby's eval and "Already initialized constant"?

I inherited maintenance on an app that uses eval() as a way to evaluate rules written in Ruby code in a rules engine. I know there are a lot of other ways to do it, but the code base so far is pretty big, and changing it to something else would be prohibitive time-wise at this point; so assume I'm stuck using eval() for the moment.
The rules as written typically call up some of the same objects from the database as each other, and the rules writer gave the variables in the rules the same names as each other. This is resulting in pages and pages of "already initialized constant" warnings in the console during development.
I'm wondering a couple things:
First, if feels like those are slowing down the execution of the program in the dev environment, and so I'm wondering if it's a big performance hit in the production environment, specifically, having those warnings pop, not eval() itself, which I know is a hit.
Second, is there any way to "namespace" the execution of each rules so that it's not defining its variables on the same scope as all the other evals in the request to avoid that warning popping all over the place? I know I could rewrite all the rules to use ||= syntax or to check if a name has already been defined, but there's quite a lot of them so I'd rather do it from the code that runs the eval()'s, if possible.
** update with example rule **
A question has a rule about when it's to be displayed to a user. For example, if the user has stated that they live in an apartment, another question might need to be shown to ask what size the apartment building is. So the second question's rule_text might look like:
UserLivesInApartment = Question.find_by_name "UserLivesInApartment"
UserLivesInApartment.answer_for(current_user)
The code that calls the eval ensures there's a current_user variable in scope prior to evaluating.
uh, eval is not perhaps the most golden of standards. You could probably fire up a drb instance and run the stuff in that instead of eval, that way you would have at least some control of what is happening and not pollute your own namespace.
http://segment7.net/projects/ruby/drb/introduction.html
Edit: added another answer for running the code in the same process:
I don't know how your rule code looks, but it might be possible to wrap a module around it:
# create a module
module RuleEngineRun1;end
# run code in module
RuleEngineRun1.module_eval("class Foo;end")
# get results
#....
# cleanup
Object.send(:remove_const, :RuleEngineRun1)
You can also create an anonymous module with Module.new { #block to be module eval'd } if you need to run code in parallel.
In later rubies you can add -W0 to run your code without printing warnings, but doing so makes possible errors go unnoticed:
$ cat foo.rb
FOO = :bar
FOO = :bar
$ ruby foo.rb
foo.rb:2: warning: already initialized constant FOO
$ ruby -W0 foo.rb
You could also run your eval inside a Kernel.silence_warnings block, but might be devastating as well if you actually run into some real problems with the eval'd code, see
Suppress Ruby warnings when running specs

Ruby debugging and console

can anyone suggest a nice (not Netbeans) platform where i would be able to write ruby code to test?
I find irb a bit hard to follow when you want to define a method more than 3 lines long, and then test it.
Also, maybe just as a wish list item, some way where I could do follow the code step by step to monitor values in variables and make sure things are being done properly?
I'm asking because so far I've been writing in rails, but what you see is the final result of the method, and if you already expected a certain answer, then is fine, but if I need a more complicated method, i would like to be able to follow all the steps to make sure is doing what I want it to do.
Thanks a lot!
a great ide is rubymines by intellij. it is not free though. you can step through code and have the usual ide debugging features.
otherwise if the only problem you have is that you are examining code that is more than 3 lines, you can install the ruby-debug gem and then put the keyword debugger in your code and it will cause a break. So you don't need to put code into irb, just run your ruby script and it will break.
I know you said you find irb a bit hard to follow when you want to define a method more than 3 lines long, but if you use irb -rn ./(your file name here), you will get an irb output of every class, method, module, etc.
irb will walk through line by line so you can see what is working and what is not (you'll get true, false, nil, etc) for each line of code. I've found that you can skip what you already know is working and move on to where you feel the issues are.

Where can I find an actively developed lint tool for Ruby?

Most of the code I write is in Ruby, and every once in a while, I make some typo which only gets caught after a while. This is irritating when I have my scripts running long tasks, and return to find I had a typo.
Is there an actively developed lint tool for Ruby that could help me overcome this? Would it be possible to use it across a system that works with a lot of source files, some of them loaded dynamically?
Take this snippet as an example:
a = 20
b = 30
puts c
To win bounty, show me a tool that will detect the c variable as not created/undefined.
ruby -c myfile.rb will check for correct Ruby syntax.
Reek checks Ruby code for common code smells.
Roodi checks Ruby code for common object-oriented design issues.
Flog can warn you about unusually complex code.
[Plug] If your project is in a public Github repository, Caliper can run the latter three tools and others on your code every time you commit. (Disclaimer: I work on Caliper)
You could give Diamondback Ruby a try. It does a static typecheck of Ruby code, and will thus blame you for using an undefined variable.
While DRuby is an ongoing research project, it already works quite well for small, self-contained Ruby scripts. Currently, it is unable to analyze much of the Ruby standard library “out-of-the-box”. Currently they are working toward typing Ruby on Rails (see their most recent papers).
RubyMine (http://www.jetbrains.com/ruby) does the trick:
alt text http://img707.imageshack.us/img707/5688/31911448.png
None of the below will do all the analysis that RubyMine does.
NetBeans Ruby pack
Aptana RadRails
gVIM (with syntastic plugin by scrooloose)
Each of these has the capacity to identify syntax errors such as wrong number of parentheses, too many defs, ends, braces, etc. But none will identify invalid method calls the way RubyMine does.
Here's why: it's difficult.
Since Ruby is extremely dynamic (and methods like 'c' could easily be generated on the fly), any editor that tries to identify non-existent variables/methods would need to have a large part of the entire evironment loaded and multiple program flow paths constantly tested in order to get accurate 'validity' results. This is much more difficult than in Java where almost all programming is static (at least it was when I dropped that hat).
This ability to easily generate methods on the fly is one of the reasons the community holds testing to such high esteem. I really do reccomend you try testing as well.
Have a look at RuboCop. It is a Ruby code style checker based on the Ruby Style Guide. It's maintained pretty actively and supports all major Ruby implementations. It works well with Ruby 1.9 and 2.0 and has great Emacs integration.
Yes. Test::Unit
Ok, I know you already know this and that in some sense this is a non-helpful answer, but you do bring up the negative consequence of duck typing, that there kind of is (at this time) no way around just writing more tests than something like Java might need.
So, for the record, see Test::Unit in the Ruby Standard Library or one of the other test frameworks.
Having unit tests that you can run and rerun is the best way to catch errors, and you do need more of them (tests, not errors :-) in dynamic languages like Ruby...
nitpick might be what you're lookng for.
With this code:
class MyString < String
def awesome
self.gsub("e", "3").gsub("l", "1").uppercase
end
end
puts MyString.new("leet").awesome
... it outputs:
$ nitpick misspelling.rb
*** Nitpick had trouble loading "misspelling.rb":
NoMethodError undefined method `uppercase' for "133t":MyString
Nothing to report boss! He's clean!
Have not used it yet, but sounds promising (will update when I've tested this).
https://github.com/michaeledgar/laser
Static analysis and style linter for Ruby code.
Pelusa is nice, but is working in rubinius only. This shouln't be a proplem for people familar with RVM though.
avdi#lazarus:~$ irb
>> a = 20
=> 20
>> b = 30
=> 30
>> puts c
NameError: undefined local variable or method `c' for main:Object
from (irb):3
>>
There ya go, the tool is called "IRB". Do I get the bounty?
I'm only half joking. I wrote this second answer to hopefully drive home the point that in Ruby, if you want to know that something is defined or not, you have to run the code.

Can you ask ruby to treat warnings as errors?

Does ruby allow you to treat warnings as errors?
One reason I'd like to do this is to ensure that if heckle removing a line of code means that a warning occurs, I have the option of ensuring that the mutant get killed.
There is unfortunately no real way of doing this, at least not on most versions of Ruby out there (variations may exist), short of monitoring the program output and aborting it when a warning appears on standard error. Here's why:
Ruby defines Kernel.warn, which you can redefine to do whatever you wish (including exiting), and which you'd expect (hope) to be used consistently by Ruby to report warnings (including internal e.g. parsing warning), but
methods implemented natively (in C) inside Ruby will in turn directly invoke a native method called rb_warn from source/server.c, completely bypassing your redefinition of Kernel.warn (e.g. the "string literal in condition" warning, for example, issued when doing something like: do_something if 'string', is printed via the native rb_warn from source/parse.c)
to make things even worse, there is an additional, rb_warning native method, which can be used by Ruby to log warnings if -w or -v is specified.
So, if you need to take action solely on warnings generated by your application code's calling Kernel.warn then simply redefine Kernel.warn. Otherwise, you have exactly two options:
alter source/error.c to exit in rb_warn and rb_warning (and rb_warn_m?), and rebuild Ruby
monitor your program's standard error output for ': warning:', and abort it on match
You can finally do that by overriding Warning.warn like
module Warning
def warn(msg)
raise msg
end
end
This will turn the warning into an exception. This solution works at least since 2.4 branch.
You could also potentially use DTrace, and intercept the calls to rb_warn and rb_warning, though that's not going to produce exceptions you can rescue from somewhere. Rather, it'll just put them somewhere you can easily log them.

Resources