Two years ago I was feeling some pain. I was trying to find a particular helper method in one of our applications, and full-text search across an entire project was not easy to do, by default. I was using TextMate at the time, which has a full-project search feature, but unless you took the time to actually configure your project just right, it would search everything (log files, Rails, etc) and that was painful. Furthermore, I was at the command-line a lot, and it wasn’t very fun to have to switch back to TextMate just to search the project.
What I typically did was just issue a suitably arcane Unix command via the command-line:
grep "def some_helper_function" app/helpers/*.rb
That’s not too bad, really, though it gets tedious when you do it often. What’s worse is when you want to find everywhere in your project that you reference that method:
find app lib -name '*.rb' \ -o -name '*.rhtml' \ -o -name '*.rjs' \ -o -name '*.rxml' | \ xargs grep some_helper_function
That’s where the pain begins to feel crippling.
So, about that time I created a utility script, called (unimaginatively) “find”, which essentially was a thin wrapper around find+xargs+grep. Instead of the above, it let me simply say:
script/find some_helper_function
However, I could scope the search, too, for narrower (and thus faster) searches:
script/find helper "def some_helper_function"
It turned out to be so handy that we’ve since copied it to nearly all of our projects. For two years I’ve relied on this script, to the point that when I started a new (personal) project this last week, I really felt the lack.
So I got permission from David to release it as a Rails plugin. I rewrote it a bit so it doesn’t rely on find, xargs, or grep (so it can be used on more than just Unix platforms), added some simple documentation, and posted it on GitHub.
Behold: the ProjectSearch plugin for Rails.
And if you happen to be a fellow Vimmer, you might find this vim script handy, which uses script/find to search in your project:
function! RailsScriptSearch(args)
let l:savegrepprg = &grepprg
let l:savegrepformat = &grepformat
try
set grepprg=script/find
set grepformat=%f:%l:%m
execute "grep " . a:args
finally
execute "set grepformat=" . l:savegrepformat
execute "set grepprg=" . l:savegrepprg
endtry
endfunction
" search with explicitly provided arguments
command! -n=? Rgrep :call RailsScriptSearch('<args>')
" search for the word under the cursor
map <leader>rg :silent call RailsScriptSearch(expand("<cword>"))<CR>:cc<CR>
" search for the method definition of the word under the cursor
map <leader>rd :silent call RailsScriptSearch(expand("'def .*<cword>'"))<CR>:cc<CR>
Enjoy!

Jamis wrote this on Mar 09 2009 There are 19 comments.
Jonathan Weiss 09 Mar 09
Have you seen `rak`?
$ gem install rak $ rak ‘def helper’ app
Jon Canady 09 Mar 09
Are you familiar with Ack?
http://betterthangrep.com/
It’s absolutely a better tool than Grep, and it even has an existing TM plugin you might be interested in:
http://somethinglearned.com/articles/2008/06/03/ack-tmbundle-a-faster-find-in-project-for-textmate
Jamis 09 Mar 09
@Jonathan, yeah, there are a few other pure-ruby grep replacements, too. The ProjectSearch plugin isn’t a general grep replacement, though, and is handier than one in a few instances: it has knowledge of Rails project structure, and common Rails file extensions, and will only search those. This lets you save a few key strokes in your searches.
leethal 09 Mar 09
Some times, I wish XCode knew what Rails was. When you make Cocoa apps, it’s certainly handy to have direct access to APIs, auto completions of your own methods and so on.
Brandon Ferguson 09 Mar 09
Another holler for Ack. It’s straight amazing whether it’s used using the TM Bundle or just from the command line. Blazingly fast. The only thing I feel is missing (and it could be that I didn’t RTFM ) is global search and replace. And honestly that’s likely for the better.
Terje Sten Bjerkseth 09 Mar 09
If you’re using Git, take a look at git grep.
Terje Sten Bjerkseth 09 Mar 09
...and examples:
git grep -e ’#define\’—and \( -e MAX _PATH -e PATH _MAX \)
Looks for a line that has #define and either MAX _PATH or PATH _MAX.
git grep—all-match -e NODE -e Unexpected
Looks for a line that has NODE or Unexpected in files that have lines that match both.
boris 09 Mar 09
Coming from the .NET world, I would be lying if I said I didn’t miss Visual Studio for this sort of thing. Thanks for sharing your solution, Jamis. Looking forward to giving it a whirl.
Adam Bachman 09 Mar 09
I had to add a few lines to the vim script. Right after `try`
try
” get rails_root from current buffer (set by rails.vim)
let l:_buffer = bufnr(’%’)
let l:_rails_root = getbufvar(_buffer, ‘rails_root’)
exe ‘lcd ’ . l:_rails_root
set grepprg=script/find
...
I’ve setup vim to change directories based on the current buffer, which breaks the finder (can’t find script/find, can’t require from vendor/plugin, etc.). This patch interrogates the buffer for its rails_root value, which is normally set by rails.vim.
So far it seems to work for me.
Jamis 09 Mar 09
@Terje, it’s cool that git gives you that, and I’m sure it’s useful, but are those examples really clearer than, say, “script/find ‘MAX_PATH’”? The point of this plugin isn’t to give you more power, it’s a compromise that gives you easier searching at the cost of less power. If you really need the power (and I don’t argue that there are times that you will), then you can use git grep or ack or rak or even just grep—but for the common case, script/find shines.
gilltots 09 Mar 09
grep -lir “something” .
that’s all you need. it’s short to type, easy to remember, and fast.
Robin 09 Mar 09
Netbeans seems to do this with its basic FIND function, and you can jump from the “found” item to the code where it was found.
Kenn Wilson 09 Mar 09
@gilltots Except that it will also search your logs, your .svn directories, etc, which is exactly the point of this plugin: It knows about Rails and so knows which directories are relevant.
Good work. I just add it to a big project I’m on, where I’m constantly writing out long grep lines.
Mike Larkin 10 Mar 09
Anybody make a textmate bundle for this yet, or planning to?
Douglas Greenshields 10 Mar 09
A third holler for ack. I use it numerous times every day. Usage is as simple as “ack MAX _PATH”. It’ll just search likely code files, ignoring logs and hidden directories (and if there’s a type it’s skipping, you can quickly add it to .ackrc). So yes, it does the same thing as script/find! The output’s also quite pretty.
Rafa 10 Mar 09
I write a little vim function to search a text in our project and definitions methods (using ack):
http://gist.github.com/77029
Kirill Maximov 11 Mar 09
All these tricks are nice and useful, but for me they sound as old-days school. For Rails development, I use RubyMine. To go to helper declaration, I press shortcut meta-alt-shift-n and just start typing helper name. To find usages of the helper, alt-F7 on helper name (or on its usage). No need to switch to console to find anything.
Disclaimer: I work for JetBrains, creator of the RubyMine.
Mike Mondragon 11 Mar 09
Is there any reason for Vim users that this script/find is better than just using ctags to index all the source code in the project?
François Montel 14 Mar 09
Nice tool. I’ve found that the “Grep Method” command in the RubyAMP TM bundle works quite well for this. (Netbeans has a similar command.)
http://code.leadmediapartners.com/
This discussion is closed.