One of the things that takes a bit of getting used to in Ruby is the symbol datatype. It seems like they're the same thing as strings, but they're not. There's a really good explanation on O'Reilly's Ruby blog, but it gets into such an involved digression on metaprogramming while setting up its examples that it's almost more useful for understanding metaprogramming instead.
Another thing that helps -- maybe helps more -- is to look at the background. As far as I can tell, Ruby's symbols are a nearly direct transliteration of Smalltalk's symbols. There's a good post on lazy initialization in Smalltalk where Ramon Leon says, "Symbols are often used where strings might be used in languages that lack them." That's a very partisan description of a language feature, but it also really tells you everything you need to know -- if you take the time to think it through.
Take a quick look at Ramon's example code in C# and Smalltalk. Unfortunately you'll have to actually click the link, because Blogger has a number of flaws that make it essentially not useful for a code blog, and I obviously chose it pretty randomly, since a programmer whose blog is not useful as a code blog cannot be said to be somebody who researched all available blogging platforms before making his choice. But let's skate past that, since it obviously highlights my foolishness, and get to the point.
The point is that in the C# example, Ramon uses a string ("AddressSearch"), and in the Smalltalk example, he uses a symbol (#AddressSearch). Just for completeness, the Smalltalk #AddressSearch is pretty much identical to the Ruby :address_search, the only differences being capitalization and trivial syntax.
Now, I don't know C#, but I do know Java, and I do know further, that in Java, if you read Josh Bloch, you don't write your Java that way. Using Strings as flags indicating state is a big, big no-no in Bloch's book, and there's a very good reason. It's an extremely bad habit. If you have a piece of code which uses Strings to represent state, and this code is invoked very frequently, your program will create a new String with the exact same content every time it needs to represent that state. In a performance-sensitive application, the overhead will be painful. Painful in the sense of ridiculously wasteful object initialization and garbage collection, and painful also in the sense that it is ridiculously simple to avoid the problem in the first place.
Bloch's solution is to create a Java Class representing the state information, and to make state or type info within such a class static, so that it's only instantiated once, and never garbage collected. In one of his books he describes creating a very significant performance improvement with this very simple change.
It's pretty easy to see that what Bloch is actually doing is adding symbols to Java. These objects are instantiated once, and since they remain instantiated, if the program needs to represent state the same way again, it doesn't have to create a new String each time. Likewise, you don't have to deal with the pecularities of String comparison -- which in Java has more pitfalls than you might think -- because when you compare these objects to each other, you're not comparing different String objects that might hold the same value, you're simply comparing two objects which either are exactly the same object, or not. That's a lot faster for the JVM, it's less error-prone for developers, and it's also exactly what you get for free with symbols in Smalltalk and Ruby. Even better, you don't have to watch a mission-critical app slow to a grinding halt and give you pathetic performance, at a consulting gig where you're representing the company behind the language, to figure all this out. It's built in from day one. You never even need to think about it.
Ramon's statement, that strings are often used for symbols in languages that lack them, is partisan but totally true. In fact, not only is it true, but further, programmers working in languages without symbols really have to choose. They can either add symbols to their language, or the result will be applications with massively inferior performance. And companies marketing languages which lack symbols have to pay really good programmers lots and lots of money to develop "design patterns" whose sole purpose is bolting on features which Smalltalk had in 1979 (and which, for that matter, Lisp had in the 50s). That's an expensive way to design a language.
Anyway, if you're a Ruby newbie and you're still not quite sure when you should use symbols instead of strings, the answer is really, anywhere that using strings would be a hack. That is to say, if strings are only for text processing, and you're using a string in some internal, programmatic way, such as to represent state or to influence flow control, there you go, that's it, that should be a symbol. Strings are for text processing, and symbols are for everything you used to use strings for because you didn't have symbols.
By the way, the actual subject of Ramon's post -- lazy initialization -- is one place where Ruby makes even Smalltalk look clunky. This is lazy initialization in Smalltalk:
^foo ifNil: [foo := #bar]
And this is lazy initialization in Ruby:
foo ||= :bar