Now that we’re cool with Objects, lets go back to discovering the basic built-in classes of Ruby. Strings are very important in any language, so let’s work with them!
In Ruby you can make strings in three different ways:
|
|
str1 = "string" str2 = 'string' str3 = %(string) p str1 p str2 p str3 |
Output:
|
|
> ruby 01_strings.rb "string" "string" "string" |
The reason for the different methods is if having to escape quotes roughs your style. The big difference is in how Ruby interprets the single quotes vs. double quotes. In the single quotes, it will take what you written literally, and that’s it. In double quotes, it does processing on the string to see if you meant any special codes. For example, like most languages, you can use the code “\n” to denote a new line:
|
|
str1 = 'newline\nfun times\n' str2 = "newline\nfun times\n" print str1 print "\n" print str2 print "\n" |
|
|
> ruby 02_newline.rb newline\nfun times\n newline fun times |
So as you can see, the single quote literally wrote ‘\n’ whereas the double quote made it the new line character. Note that we’re using “print” instead of “p”. Print will print the literal characters to the screen, but ‘p’ will prettify it first.
Double quotes also have interpolation (variables within strings):
|
|
innerstring = 'fun' str1 = '#{innerstring} times' str2 = "#{innerstring} times" print str1 print "\n" print str2 print "\n" |
|
|
> ruby 03_interpolation.rb #{innerstring} times fun times |
Interpolation is very useful. You will be using this a lot.
Strings are cool, but what you really want is to do things to strings, so here’s just some example methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
irb # First, we just set the string 1.9.3-p286 :001 > string = "i am a string" => "i am a string" # You can add a string to another string. It returns a new string. 1.9.3-p286 :002 > string2 = string + " i too am a string" => "i am a string i too am a string" # You can use this new string anywhere. 1.9.3-p286 :003 > string2 => "i am a string i too am a string" # The old string is not modified. 1.9.3-p286 :004 > string => "i am a string" # The next few show how to get random slices out of a string. 1.9.3-p286 :005 > string[0] => "i" # The x..y syntax denotes a Range. It lets you put in two numbers to be used, very useful for string slicing, since if it sees a Integer, it thinks you want one character. This gives you a range: 1.9.3-p286 :006 > string[0..5] => "i am a" 1.9.3-p286 :007 > string[5..10] => "a stri" 1.9.3-p286 :008 > string[1000.10000] => nil 1.9.3-p286 :009 > string[1..100000] => " am a string" # You can upcase a string. 1.9.3-p286 :010 > string.upcase => "I AM A STRING" # You can also downcase a string. Since most methods return the modified string, you can chain methods. 1.9.3-p286 :011 > string.upcase.downcase => "i am a string" # You can concatenate to a string. 1.9.3-p286 :017 > string.concat(" i too am a string") => "i am a string i too am a string" # This modifies the string. 1.9.3-p286 :018 > string => "i am a string i too am a string" # You can get a length. 1.9.3-p286 :019 > string.length => 31 # You can prepend a string. 1.9.3-p286 :020 > string.prepend("hi there") => "hi therei am a string i too am a string" # You can use gsub to do string replacement. Note that gsub doesn't modify the original string. 1.9.3-p286 :021 > string.gsub("string", "bytearray of text") => "hi therei am a bytearray of text i too am a bytearray of text" 1.9.3-p286 :022 > string => "hi therei am a string i too am a string" # However, gsub! does modify the string. 1.9.3-p286 :023 > string.gsub!("string", "bytearray of text") => "hi therei am a bytearray of text i too am a bytearray of text" 1.9.3-p286 :024 > string => "hi therei am a bytearray of text i too am a bytearray of text" |
Just so it isn’t obvious, you can use “#” at the beginning to denote a comment, like in most other shell-type languages. (You can’t use C-style “//” for a comment.)
For the curious, there are more things you and do to a string list in the core documentation. This just scratches the surface, see the “%” for sprintf style stuff, or the centering, or stripping.
Also, just so it’s mentioned but it’s rarely used is the multiline string:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
multiline1 = <<-eos Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. eos multiline2 = %(Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.) multiline3 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." print "#{multiline1}\n#{multiline2}\n#{multiline3}\n" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
>ruby 04_multiline_string.rb Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. |
The differences are mostly based on preference. All three support interpolation and stuff.
Symbols
There are special strings in Ruby called Symbols. Think of them as Diet Strings, as they are stored differently. While a String is a lot like a C-based char[] array where it will store the data for each one (in fact, that’s how Ruby does it internally), Symbols have their data in the symbol table and looked up from there. This is very useful for when you’re passing around configuration or column data, which you want to add headers to the data.
For example, you might see something in Ruby like:
|
|
Object.some_cool_function(:yes) |
The “:yes” part is a symbol:
|
|
irb 1.9.3-p286 :001 > :yes => :yes 1.9.3-p286 :002 > :yes.class => Symbol |
If you’re going to be passing information around, a Symbol is like a giant set of enums. That way you’re not creating a new string each time you want to pass information, when an enum could suffice for what that information is. Since it has a look up table, you can just simply convert it to a string, and it auto-converts on interpolation:
|
|
irb 1.9.3-p286 :001 > sym = :yes => :yes 1.9.3-p286 :002 > sym.to_s => "yes" 1.9.3-p286 :003 > mbison_says = "#{sym}! YES!" => "yes! YES!" |
You shouldn’t be using Symbols as you would a String. But it makes sense when you have a need for enums or diet strings.
There are some instances where Ruby requires a Symbol instead of a String. For example due to the Objectness of Ruby, you can actually call any method using __send__, so the following are the same:
|
|
irb 1.9.3-p286 :001 > string = "Why yes, I am a string!" => "Why yes, I am a string!" 1.9.3-p286 :002 > string+" I am a string too!" => "Why yes, I am a string! I am a string too!" 1.9.3-p286 :003 > string.+(" I am a string too!") => "Why yes, I am a string! I am a string too!" 1.9.3-p286 :004 > string.__send__(:+," I am a string too!") => "Why yes, I am a string! I am a string too!" |
So the first two you are familiar with. In the previous part, I showed that since everything is an object, you can call everything’s function like an object. Ruby just assumes that if you do “object1 + object2″, it just interprets it as “object1.+(object2)” because it makes the code look pretty. But you can also have it run any method using “__send__” where it requires the name of the method as a symbol. (Since method names are stored internally as a symbol. Make sense, since method names are used often enough to be necessary as an enum or diet string.)
Anyway, if you see example code that uses Symbols, use that instead. Diet Strings are very useful for performance; if you’re using a string as a information token where a random integer could provide the same information (like an enum), use a symbol.