Data Types

While everything in Ruby is an object, some of the data types in Ruby have special syntax support, in particular for defining literal values. In the preceding examples, we used some simple strings and even string concatenation.

Strings

The previous example also showed some Ruby string objects. One way to create a string object is to use string literals, which are sequences of characters between single or double quotation marks. The difference between the two forms is the amount of processing Ruby does on the string while constructing the literal. In the single-quoted case, Ruby does very little. With only a few exceptions, what you type into the single-quoted string literal becomes the string’s value.

With double-quotes, Ruby does more work. It looks for substitutions—sequences that start with a backslash character—and replaces them with a binary value. The most common of these is , which is replaced with a newline character. When you write a string containing a newline to the console, the forces a line break.

Then, Ruby performs expression interpolation in double-quoted strings. In the string, the sequence #{expression} is replaced by the value of expression. We could use this to rewrite our previous method:

 def​ ​say_goodnight​(name)
 "Good night, ​​#{​name.​capitalize​​}​​"
 end
 puts say_goodnight(​'pa'​)

When Ruby constructs this string object, it looks at the current value of name and substitutes it into the string. Arbitrarily complex expressions are allowed in the #{…} construct. Here we invoked the capitalize method, defined for all strings, to output our parameter with a leading uppercase letter.

Strings are a fairly primitive data type that contain an ordered collection of bytes or characters. Ruby also provides means for defining collections of arbitrary objects via arrays and hashes.

Arrays and Hashes

Ruby’s arrays and hashes are indexed collections. Both store collections of objects, accessible using a key. With arrays, the key is an integer, whereas hashes support any object as a key. Both arrays and hashes grow as needed to hold new elements. It’s more efficient to access array elements, but hashes provide more flexibility. Any particular array or hash can hold objects of differing types; you can have an array containing an integer, a string, and a floating-point number, for example.

You can create and initialize a new array object by using an array literal—a set of elements between square brackets. Given an array object, you can access individual elements by supplying an index between square brackets, as the next example shows. Ruby array indices start at zero:

 a = [ 1, ​'cat'​, 3.14 ] ​# array with three elements
 a[0] ​# access the first element (1)
 a[2] = ​nil​ ​# set the third element
 # array now [ 1, 'cat', nil ]

You may have noticed that we used the special value nil in this example. In many languages, the concept of nil (or null) means no object. In Ruby, that’s not the case; nil is an object, like any other, that happens to represent nothing.

The << method is often used with arrays. It appends a single value to its receiver:

 ages = []
 for​ person ​in​ @people
  ages << person.​age
 end

Ruby has a shortcut for creating an array of words:

 a = [ ​'ant'​, ​'bee'​, ​'cat'​, ​'dog'​, ​'elk'​ ]
 # this is the same:
 a = ​%w{ ant bee cat dog elk }

Ruby hashes are similar to arrays. A hash literal uses braces rather than square brackets. The literal must supply two objects for every entry: one for the key, the other for the value. For example, you may want to map musical instruments to their orchestral sections:

 inst_section = {
 :cello​ => ​'string'​,
 :clarinet​ => ​'woodwind'​,
 :drum​ => ​'percussion'​,
 :oboe​ => ​'woodwind'​,
 :trumpet​ => ​'brass'​,
 :violin​ => ​'string'
 }

The thing to the left of the => is the key, and that on the right is the corresponding value. Keys in a particular hash must be unique; if you have two entries for :drum, the last one will win. The keys and values in a hash can be arbitrary objects: you can have hashes in which the values are arrays, other hashes, and so on. In Rails, hashes typically use symbols as keys. Many Rails hashes have been subtly modified so that you can use either a string or a symbol interchangeably as a key when inserting and looking up values.

The use of symbols as hash keys is so commonplace that Ruby has a special syntax for it, saving both keystrokes and eyestrain:

 inst_section = {
 cello: ​​'string'​,
 clarinet: ​​'woodwind'​,
 drum: ​​'percussion'​,
 oboe: ​​'woodwind'​,
 trumpet: ​​'brass'​,
 violin: ​​'string'
 }

Doesn’t that look much better?

Feel free to use whichever syntax you like. You can even intermix usages in a single expression. Obviously, you’ll need to use the arrow syntax whenever the key is not a symbol. One other thing to watch out for: if the value is a symbol, you’ll need to have at least one space between the colons or else you’ll get a syntax error:

 inst_section = {
 cello: :string​,
 clarinet: :woodwind​,
 drum: :percussion​,
 oboe: :woodwind​,
 trumpet: :brass​,
 violin: :string
 }

Hashes are indexed using the same square bracket notation as arrays:

 inst_section[​:oboe​] ​#=> :woodwind
 inst_section[​:cello​] ​#=> :string
 inst_section[​:bassoon​] ​#=> nil

As the preceding example shows, a hash returns nil when indexed by a key it doesn’t contain. Normally this is convenient, because nil means false when used in conditional expressions.

You can pass hashes as parameters on method calls. Ruby allows you to omit the braces, but only if the hash is the last parameter of the call. Rails makes extensive use of this feature. The following code fragment shows a two-element hash being passed to the redirect_to method. Note that this is the same syntax that Ruby uses for keyword arguments:

 redirect_to ​action: ​​'show'​, ​id: ​product.​id

One more data type is worth mentioning: the regular expression.

Regular Expressions

A regular expression lets you specify a pattern of characters to be matched in a string. In Ruby, you typically create a regular expression by writing /pattern/ or %r{pattern}.

For example, we can use the regular expression /Perl|Python/ to write a pattern that matches a string containing the text Perl or the text Python.

The forward slashes delimit the pattern, which consists of the two things that we’re matching, separated by a vertical bar (|). The bar character means either the thing on the left or the thing on the right—in this case, either Perl or Python. You can use parentheses within patterns, just as you can in arithmetic expressions, so we could also write this pattern as /P(erl|ython)/. Programs typically use the =~ match operator to test strings against regular expressions:

 if​ line =~ ​/P(erl|ython)/
  puts ​"There seems to be another scripting language here"
 end

You can specify repetition within patterns. /ab+c/ matches a string containing an a followed by one or more bs, followed by a c. Change the plus to an asterisk, and /ab*c/ creates a regular expression that matches one a, zero or more bs, and one c.

Backward slashes start special sequences; most notably, d matches any digit, s matches any whitespace character, and w matches any alphanumeric (word) character, A matches the start of the string and z matches the end of the string. A backslash before a wildcard character, for example ., causes the character to be matched as is.

Ruby’s regular expressions are a deep and complex subject; this section barely skims the surface. See the PickAxe book for a full discussion.

This book will make only light use of regular expressions.

With that brief introduction to data, let’s move on to logic.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.203.68