Value: High
Level: Easy
Summary:
• First and foremost, run your scripts with warnings enabled (the -w
command-line option).
• If you happen to forget a "," in an argument list—especially to
print—you can produce some very odd error messages.
• A parse error at the last line of the source often indicates a
missing end keyword, sometimes quite a bit earlier.
• An attribute setter is not being called. Within a class definition,
Ruby will parse setter= as an assignment to a local variable, not as a
method call. Use the form self.setter= to indicate the method call
(example code 1).
• Objects that don't appear to be properly set up may have been
victims of an incorrectly spelled initialize method (example code 2).
The same kind of thing can happen if you misspell the instance
variable name (example code 3).
• Block parameters are in the same scope as local variables. If an
existing local variable with the same name as a block parameter exists
when the block executes, that variable will be modified by the call to
the block. This may or may not be a Good Thing (example code 4).
• Watch out for precedence issues, especially when using {} instead of
do/end (example code 5).
• If numbers don't come out right, perhaps they're strings. Text read
from a file will be a String and will not be automatically converted
to a number by Ruby. A call to Integer will work wonders (and will
throw an exception if the input isn't a well-formed integer).
• Unintended aliasing—if you are using an object as the key of a hash,
make sure it doesn't change its hash value (or arrange to call
Hash#rehash if it does) (example code 6).
• Make sure the class of the object you are using is what you think it
is. If in doubt, use puts my_obj.class.
• Make sure your method names start with a lowercase letter and class
and constant names start with an uppercase letter.
• If method calls aren't doing what you'd expect, make sure you've put
parentheses around the arguments.
• Make sure the open parenthesis of a method's parameter list butts up
against the end of the method name with no intervening spaces.
• Use irb and the debugger.
• Use Object#freeze. If you suspect that some unknown portion of code
is setting a variable to a bogus value, try freezing the variable. The
culprit will then be caught during the attempt to modify the variable.
Memo: One major technique makes writing Ruby code both easier and more
fun. Develop your applications incrementally. Write a few lines of
code, and then run them. Perhaps use Test::Unit to write some tests.
Write a few more lines of code, and then exercise them. One of the
major benefits of a dynamically typed language is that things don't
have to be complete before you use them.
Example:
class Incorrect
attr_accessor :one, :two
def initialize
one = 1 # incorrect - sets local variable
self.two = 2
end
end
obj = Incorrect.new
obj.one → nil
obj.two → 2
class Incorrect
attr_reader :answer
def initialise # < < < spelling error
@answer = 42
end
end
ultimate = Incorrect.new
ultimate.answer → nil
class Incorrect
attr_reader :answer
def initialize
@anwser = 42 #<« spelling error
end
end
ultimate = Incorrect.new
ultimate.answer → nil
c = "carbon"
i = "iodine"
elements = [ c, i ]
elements.each_with_index do |element, i|
# do some chemistry
end
c → "carbon"
i → 1
def one(arg)
if block_given?
"block given to 'one' returns #{yield}"
else
arg
end
end
def two
if block_given?
"block given to 'two' returns #{yield}"
end
end
result1 = one two {
"three"
}
result2 = one two do
"three"
end
puts "With braces, result = #{result1}"
puts "With do/end, result = #{result2}"
arr = [1, 2]
hash = { arr => "value" }
hash[arr] → "value"
arr[0] = 99
hash[arr] → nil
hash.rehash → {[99, 2]=>"value"}
hash[arr] → "value"
Reported errata (at 10/17/06 14:17:18 PDT): 1
*See below
Errata I found: 1
*Reported erratum #2822 refers to page 133, not to page 161 as stated.
My suggestions to the author: 0
Doubts: 2
*I didn't understand example code 5.
*"Output written to a terminal may be buffered. This means you may not
see a message you write immediately. In addition, if you write
messages to both $stdout and $stderr, the output may not appear in the
order you were expecting. Always use nonbuffered I/O (set sync=true)
for debug messages." What does it mean ?