finding a stray puts in ruby code - ruby-on-rails

We have a fairly large rails application and I have started this output in our unicorn.log:
#:0xc644248>#:0xc644248>#:0xc4f06e4>#:0xc4f06e4>#:0xca481b4>#:0xca481b4>#:0xc53f604>#:0xc53f604>#:0xcd7a60c>#:0xcd7a60c>#:0xc5df2f8>#:0xc5df2f8>#:0xc69fd00>#:0xc69fd00>#:0xc560ae8>#:0xc560ae8>
It seems to me like there probably is a stray Kernel.puts method call somewhere, but I've been searching for hours and can't find it.
Anyone have tips for tracking something like this down?

You could monkey patch puts, and raise an exception when it's called. You could even fine tune that with a regexp match on your output string (which looks like a recursive object dump).
module Kernel
def puts (s)
raise "puts called, check the backtrace for the source" if s =~ /#:[a-z0-9]>*/
end
end
It could also be that it's not a call to puts, but rather #inspect.

Have you checked for display? That's another method that prints stuff out.

You could go over all the files and search for any calls to Kernel.puts, like so:
find -iname "*.rb" | xargs grep -iR 'Kernel.puts'
However, in terms of neatness (and effectiveness), I would probably go for the solution provided by Jeff Paquette.

This is what I use, it's similar to Banang's answer but maybe even simpler. Do a grep from the directory like so:
grep -rn 'puts' .
Sure it searches everything but you can run it in whatever directory you want to limit that. That should give you the file and line number you need. You can fine tune the search criteria as you wish.

Related

Showing only specific test case in test.log

I am writing Rails tests using the standard Test::Unit/TestCase.
Is there any way to somehow filter what gets printed to the log, so that you only print the stack for specific test cases.
I have a functional test file with many test cases in it, and I'm really only interested in debugging one test case. Printing my own log statements still requires searching through a few thousand lines of generated log. Or something similar to the RSpec 'pending' functionality.
Run from a command line ruby test/unit/my_model.rb to run one test suite. You can also use a debugger, such as (wrapped by) RubyMine or pry, to stop on a specific test case and look at the log.
But if a sledge-hammer does not solve the problem, you can use tweezers: config.logger.level = Logger::WARN in your test.rb, from Set logging levels in Ruby on Rails
It is probably better if instead of strangling the output to log/test.log, you become familiar with a command such as grep. Grep allows you to run very advanced search queries through files or directories, as long as your running on some flavor of *nix. The simplest use would be
grep search_term file_name
The reason I say you shouldn't constrict the log output is because someday that could bit you in the **s. Hope this helps.

What are best practices for tracing the flow of a large rails app?

If you are a new developer to a large (very large!) rails app it can be really difficult to trace through the flow of what is calling what, where a method is defined, and how to 'grok' how the whole thing works.
What are best practices for how to find information like:
I'm in class Foo and it calls a method bar but there is no def bar in the file. It must be mixed in or a concern or monkey patched etc. in somehow. What are steps 1, 2, 3 for where to look? I don't see anything obvious at the top of the file and greping for 'def bar' doesn't return anything.
Metaprogramming! Probably defined the methods on the fly based on the params passed. Ex. define_method
I would go with
grep "def bar" app/* lib/* -irn (optionally -l)
If I'm in the file open, I most likely would use cscope, because I use vim, but if you are using an IDE it might help you somehow to find this method.
Or yet, I could simply use the debugger, where you can inspect your objects in runtime.

Tool/gem to find commented code

Over the course of our project with multiple developers and styles, we have some tests and code that are commented out. Is there an easy way to find all code that is commented out?
The tool should be smart enough to find out that it is ruby code that is being commented not, real comments.
At this point I can only think of grep like grep #, but it should be something smarter and less manual.
This may be ugly but I think you can inspect each ".rb" file with a rake task, line per line, matching it with a regexp (something like /#.*\n/), and run an eval("matching_string") on each match. If the comment isn't ruby code it will simply fail.
It seems you'll need a looks_like_ruby method so you can do this:
puts line if line =~ /^\s+#/ && looks_like_ruby(line)
A quick and dirty implementation (off the top of my head)
def looks_like_ruby(text)
text =~ Regexp.union((Kernel.methods + Object.methods).uniq.map(&:to_s))
end
Not perfect, but better than grepping for #

puts statements for debug

When I code, I make quite intense use of "puts" statements for debugging. It allows me to see what happens in the server.
When the code is debugged, I use to remove these "puts" statements for I don't know what reason.
Is it a good idea or should I leave them instead to give more clarity to my server logs?
You should use the logger instead of puts. Use this kind of statements:
Rails.logger.debug "DEBUG: #{self.inspect} #{caller(0).first}" if Rails.logger.debug?
If you want to see the debugging in the real-time (almost), just use the tail command in another terminal window:
tail -F log/development.log | grep DEBUG
Then you do not need to remove these statements in production, and they will not degrade performance too much, because if logger.debug? will prevent the (possibly expensive) construction of the message string.
Using standard output for debugging is usually a bad practice. In cases you need such debug, use the diagnostic STDERR, as in:
STDERR.puts "DEBUG: xyzzy"
Most of the classes in Rails (models, controllers and views) have the method logger, so if possible use it instead of the full Rails.logger.
If you are using older versions of Rails, use the constant RAILS_DEFAULT_LOGGER instead of Rails.logger.
use the logger : http://guides.rubyonrails.org/debugging_rails_applications.html#the-logger
I use the rails_dt gem designed specifically to make such kind of debugging easier.
Using Rails.logger or puts directly is somewhat cumbersome, since it requires you to put a lot of decorative stuff (DEBUG, *** etc.) around debug messages to make them different from regular, useful messages.
Also, it's often difficult to find and defuse the debug output generated by Rails.logger or puts if the message doesn't appear to contain enough searchable characters.
rails_dt prints the origin (file, line), so finding the position in code is easy. Also, you will never confuse DT.p with anything, it clearly does debug output and nothing else.
Example:
DT.p "Hello, world!"
# Sent to console, Rails log, dedicated log and Web page, if configured.
[DT app/controllers/root_controller.rb:3] Hello, world!
Gem is available here.

Problem with Ruby OmniComplete in Vim 7.3 finding matches at one line but not 2 lines down

Im trying to figure out why ruby omnicompl only works sometimes for me.
Here it's working as expected.
But when I try the same thing on the same ivar 2 lines down I get "Pattern not found"
Both are done the same way, typing out #current_user_session.fiCtrl+X+O
I checked tpopes rails.vim github page for open/closed issues and tried to google it without luck.
My macvim and vim is compiled with +ruby
:echo &omnifunc returns rubycomplete#Complete
:Rails! returns rails.vim 4.3 (Rails-controller)
I have my complete vimdir on github for reference.
one would imagine that it's because in img2 it's now below the setting of the variable (#current_user_session = UserSession.find).
which means that as this is now an instance it's looking for instance methods, whereas before it was returning the class method.
e.g.
User.find # => fine
user = User.find
user.find # => Method not found
to demo the difference run these:
User.methods.sort
User.find.methods.sort
you'll see that it's quite different. put bluntly you're trying to look up 'find' for a user you have. "'tom'.find" doesn't make any sense.

Resources