Testing Whether an Object Is String-Like

Problem

You want to see whether you can treat an object as a string.

Solution

Check whether the object defines the to_str method.

	'A string'.respond_to? :to_str # => true
	Exception.new.respond_to? :to_str # => true
	4.respond_to? :to_str # => false

More generally, check whether the object defines the specific method of String you're thinking about calling. If the object defines that method, the right thing to do is usually to go ahead and call the method. This will make your code work in more places:

	def join_to_successor(s)
	 raise ArgumentError, 'No successor method!' unless s.respond_to? :succ
	 return "#{s}#{s.succ}"
	end

	join_to_successor('a') # => "ab"	
	join_to_successor(4) # => "45"
	join_to_successor(4.01)
	# ArgumentError: No successor method!

If I'd checked s.is_a? String instead of s.respond_to? :succ, then I wouldn't have been able to call join_to_successor on an integer.

Discussion

This is the simplest example of Ruby's philosophy of "duck typing:" if an object quacks like a duck (or acts like a string), just go ahead and treat it as a duck (or a string). Whenever possible, you should treat objects according to the methods they define rather than the classes from which they inherit or the modules they include.

Calling obj.is_a? String will tell you whether an object derives from the String class, but it will overlook objects that, though intended to be used as strings, don't inherit from String.

Exceptions, for instance, are essentially strings that have extra information associated with them. But they don't subclass class name "String". Code that uses is_a? String to check for stringness will overlook the essential stringness of Exceptions. Many add-on Ruby modules define other classes that can act as strings: code that calls is_a? String will break when given an instance of one of those classes.

The idea to take to heart here is the general rule of duck typing: to see whether provided data implements a certain method, use respond_to? instead of checking the class. This lets a future user (possibly yourself!) create new classes that offer the same capability, without being tied down to the preexisting class structure. All you have to do is make the method names match up.

See Also

  • Chapter 8, especially the chapter introduction and Recipe 8.3, "Checking Class or Module Membership"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net