How can I find unused methods in a Ruby app? - ruby

I have a Ruby app with a lot of classes/modules, and some of them are not used. Is there an easy way of finding out which?
I was thinking to do a profile, and then work with it's output. Any other ideas?

A coverage tool, like rcov might help.
https://github.com/relevance/rcov
As you find methods that are not covered by tests, you should write tests for them or find out if they are used at all.
Removing unused methods is part of refactoring, if you have too many classes that can be a code smell that needs refactored also.

You can put raise (or raise Exception if you don't want it caught) to the start of the suspect method. If nothing breaks, then it might not be in use (either that, or something's catching the exceptions).

Related

Preventing debugging from stopping at core library modules?

When I start debugging using:
ruby -rdebug file.rb
and place break points:
b path:linenumber
before it gets to my break point, it stops at many other points in the imported libraries.
Does any one know how to prevent that?
Note: I already know I can place debugger points in the code which works well, but I do not want to do that since I keep forgetting to remove them.
I'm more thinking of a solution like using an option to prevent stopping at any module under /usr/lib/ruby.
I haven't used rdebug at all yet, but I've been having a great experience using Pry (http://pryrepl.org/). You simply stick a binding.pry anywhere in your code and upon execution you'll get dropped into the context of your binding.pry. You can then inspect variables, methods, navigate to different contexts using ls and cd, etc.
Sorry if this isn't what you were looking for!

What is the reason for the MSpec library?

I've been reading the README for the MSpec project, and though it does a lot of explaining about what it is and (what it is not) with several contrasts between itself and RSpec, there's nothing about why it exists. Would using RSpec (at the time of starting MSpec) have caused problems in some way, or was it missing some features? Are these things still true? Could an extension have been (or be) written for RSpec that would do this? Is it something political?
There's obviously a lot of documentation and examples for RSpec, more features and more updates to the library, and since MSpec seems harder to use IMO (considering the differences in feature set and my own comfort level with RSpec) I'd be very interested if anyone knows the reasons. Perhaps that sounds critical, but that's not my point, I'm just trying to supply some context - there are likely to be good reasons for all of this and that's what I wish to find out.
From the README:
MSpec attempts to use the simplest Ruby language features so that beginning
Ruby implementations can run the Ruby specs.
This was designed for incomplete implementations (Specifically Rubinius) of the base Ruby language. It doesn't use all the language features of Ruby, so it's easier to bootstrap your implementation to the point where you can run mspec's.
If you aren't creating a new implementation for the Ruby language, then you shouldn't use this.

Using RJB to call scala code from Ruby

I'm about to start rewriting bits and pieces of our Rails app that do the relatively heavier number crunching in Scala for speed. The plan eventually is to have all the processing done by a scala daemon running in the background and just use Rails for the frontend, but in the meantime I want to be able to rewrite bits and pieces of the slower code now and call them synchronously from Ruby.
For this reason I've been looking at RJB (I can't use JRuby) in the hope that I can use it with scala too, seeing as it compiles to Java Bytecode in the end anyway. I've had a google around to see if I can find someone who's already done this or similar but not come up with anything.
My inital, naive attempt was to just compile and package a test scala class into a jar and try loading it using Rjb like this:
Rjb::load("#{Rails.root}/lib/scala/scala-tester-1.0-SNAPSHOT.jar")
MyClass = Rjb::import('com.mydomain.MyClass')
But this just results in a java.lang.NoClassDefFoundError: com/mydomain/MyClass.
I tested importing a standard java class, which works fine, so I tested importing scala.Int, which resulted in another NoClassDefFoundError. This sort of suggests to me that the problem may lie in the scala libraries not being included on the classpath? But it's quite a while since I've had to deal with the endless headaches of Java classpaths so I'm pretty rusty at diagnosing and fixing this kind of problem.
So, has anyone done this? If not, does my hunch sound correct? Any suggestions? Or is there something I'm not thinking of that will mean this approach won't work at all?
EDIT: realised I'd been using slightly incorrect syntax. Have now managed to get it to load my test jar using syntax like this:
Rjb::load(classpath = "#{Rails.root}/lib/scala/scala-tester-1.0-SNAPSHOT.jar", jvmargs=[])
but fail with a different java.lang.NoClassDefFoundError: scala/ScalaObject which suggests it definitely is failing to load the scala libraries.
I got it to work with the following:
RJB_LOAD_PATH = ["#{ENV['SCALA_HOME']}/lib/scala-library.jar", "#{Rails.root}/lib/scala/scala-tester-1.0-SNAPSHOT.jar"].join(File::PATH_SEPARATOR)
RJB_OPTIONS = []
Rjb::load(RJB_LOAD_PATH, RJB_OPTIONS)
Going to put this code in an initializer but it still seems a little hacky and would be glad to hear if anyone has any neater suggestions.

How do you remove functionality from a program in ruby?

You have some code you want to remove associated with an obsolete piece of functionality from a ruby project. How do ensure that you get rid of all of the code?
Some guidelines that usually help in refactoring ruby apply, but there are added challenges because having code that isn't being called by anything won't break any unit tests.
Update: Has anyone written anything that allows you to guess based on your version control history if there are commits where you have since deleted most, but not all, of the code and can point out the remaining code?
Current thoughts:
Identify the outermost part of the stack associated with the obsolete functionality: the binary script calling it, or the unit tests calling it.
Look for methods that are only called by methods associated with the obsolete functionality. I often use git grep for this.
In theory, running mutation testing and looking for code that used to be mutation resistant when the old test suite applied, but is now mutation prone might help. It only helps if your code was well-tested in the first place! (Or you can use code coverage tools such as rcov rather than mutation testing)
Running test suites will ensure you haven't removed anything you shouldn't have!
Using autotest can save you time if you're constantly running tests.
If your code was well-structured, it should be easier to find related methods that need to be removed.
Especially in a dynamically typed language, there is no easy way to do this. If you have unittests, thank the developer that wrote them because it will help you remove the code correctly. But you're basically SOL. Remove the code, if it breaks, put it back, figure out where it broke, attempt to work around it, and repeat.
Look at your code coverage. Any code which isn't covered may be part of the code you have left to remove (if any). (Just be sure you have removed you tests. =])

What is the ruby test tool called that 'breaks' your code to see how tight your tests are?

A wee while ago I ended up on a page which hosted several ruby tools, which had 'crazy' names like 'mangler' or 'executor' or something. The tool's job was to modify you production code (at runtime) in order to prove that your tests were precise.
Unfortunately I would now like to find that tool again, but can't remember what it was called. Any ideas?
I think you're thinking about Heckle, which flips your code to make sure your tests are accurate. Here:
http://seattlerb.rubyforge.org/heckle/
Maybe you're thinking of the Flay project and related modules:
http://ruby.sadi.st/Ruby_Sadist.html
Also you can try my mutant. Its AST based and currently runs under MRI and RBX in > 2.0 mode. It only has a killer for rspec3, but others are possible also.

Resources