Day 12: Continuing through Chapter 4

I am back at it.

So, I left off at 4.3 Other Data Structures. This part starts out talking about arrays and ranges. An array is just a list of elements in a particular order.

As you can see, the “split” method divides this string along the whitespace. This is the default method. You can split on nearly anything however. Notice we split along “x” here:

Below, we will set “a” as an array, and then can ask it what various elements in the array are. As is the convention in most computer languages, Ruby arrays are zero-offset, meaning the first element is 0, not 1.

As seen above, Ruby accesses arrays using bracket notation. You can also use synonyms for commonly accessed elements:

We can also use the “==” operator to do a comparison, the below asking whether the last element is also the -1 element.

We can also demonstrate that like a string, an array responds to the “length” method. Also, you can use other operators to compare in Ruby, such as the “!=” which is “not equal.”

You can also use other methods within Ruby on the array. You can ask whether it is “empty” use the method “.empty?”

Ask whether it “includes” a certain element using “.include?” and putting the element you seek in parentheses.

You can also sort it, reverse it, and shuffle it!

Notice that despite it being reversed and shuffled, the array remains the original pattern. To have Ruby keep the order when sorting you add a “bang” at the end, like so:

We can also add elements to the array using “push” as well as “<<"

You can also chain together the adding of elements, like so: >> a << "foo" << "bar" => [8, 17, 42, 6, 7, “foo”, “bar”]

This also demonstrates that you can add strings into the array. Using the method “.join” you can put these together.

As well join them together with commas.

This is because the array was not saved in the “.join” state.

Not, let’s look at ranges. These are similar to arrays. You can understand the difference when a range is converted to an array:

What happened here is, like the method “.to_s” to convert an element to a string, we attampted to use “.to_a” to convert the range to an array. Unfortunately, Ruby didn’t understand it. We need to use parentheses to define the range, like so:

Ranges are useful for pulling out array elements. Below, we will use %w to make a string array. I like this because I am lazy and who really wants to put quotation marks around all those strings?

And you can use the range to pull out array elements:

You can also use the “-1” index at an end of a range to select all the elements from your starting point to the end without having to use the array’s length:

You can also use a range with characters, like so:

Now it is time to move on to blocks. Mr. hartl explains that the block is “one of Ruby’s most powerful and most confusing features.” Let’s take a look, and I will try to get my head wrapped around it:

Alright, so the first line shows us putting the range 1..5 into an array. Now, after this we take this range and call the “.each” method on it. It is then passed to the block which is this:

The vertical bars, I’ve also heard them called pipes around the “i” are Ruby syntax for a block variable. So, if I understand correctly, it takes each element in the range, which is “1, 2, 3, 4, and 5” and multiplies each by 2. It can also be expressed another way:

The “do” and “end” way of doing this is best for a multi-line block, like so:

You can also use any variable name:

Let’s look at a few more, first with the “times” method:

Here, the 3.times passes through the block, summoning Beetlejuice.

Next, we will look at a block and use the “map” method. The first takes the range, (1..5) and applies the “.map” method. It passes it to the block, { |i| i**2 } where it is squared by 2. The “**” is how Ruby notates “power.”

This took me a bit to understand and I had to go and compare it to how each outputs. The .map method maps the results into an array, as best as I can figure out. Here are a few more examples, this time using characters:

Now, I am going to stop for a second because I want to be sure I understand the difference between .map and .each. Let’s take a look at a test I just did:

It appears to me that the .map method actually applies the block on to the elements in the array. It appears the .each just passes them on without it being applied. See here:

This makes me curious. I’m going back a bit and trying the .map on the earlier blocks we tried…

I am confused but this is also very interesting. The first is the original block example in the tutorial. Notice that at the main end it outputs the original range we called. The second one is with the .map method. At the end it outputs an array of nils (If I had a band this would be my band name.)

I did end up seeking help for this, however, in the CodeNewbie Slack Channel. Practicing Ruby explained it like this:

You can think of map as just being the same as the long form “create an array, call each on another array, operate on each element, append the result to the new array”

Time for hashes and symbols!

This is an empty hash. The use of those curly brackets should not confuse you. It is not a block! The tutorial says that “Hashes are essentially arrays that aren’t limited to integer indices.”

** I am going to start using comments to talk about certain lines like the tutorial does. Probably a better way anyway! **

So, the above defines each key and value one at a time. We can also use a hashrocket to do this! This is a hashrocket: =>

According to the tutorial, it is much more common for symbols to be used as has keys then strings. A symbol is prefixed with a colon, like this :name

Mr. Hartl describes the symbol as having less baggage than a string. See this:

but try it with a symbol:

and we get an error. Same with trying to reverse.

Also, stick with normal characters, letters and numbers. Ruby don’t like it:

So let’s try some symbols with our hashes!

>> user = { :first_name => “Atticus”, :last_name => “O’Sullivan” }
=> {:first_name=>”Atticus”, :last_name=>”O’Sullivan”}

There is also a new syntax that can be used in Ruby versions as of 1.9 that takes away the hashrockets but still defines the values to symbols as keys, like so:

Hash values can be anything, including other hashes. Hashes of hashes are nested hashes. Here is an example:

Hashes will also respond to the .each method

>> flash = { success: “It worked!”, danger: “It failed.” }
=> {:success=>”It worked!”, :danger=>”It failed.”}
>> flash.each do |key, value|
?> puts “Key #{key.inspect} has value #{value.inspect}”
>> end
Key :success has value “It worked!”
Key :danger has value “It failed.”
=> {:success=>”It worked!”, :danger=>”It failed.”}

And, the above uses the method “.inspect” that returns a literal representation of the object its called on. The use of inspect to print an object is so common that there is a shortcut for it:

Its the p function!

So, at this point the tutorial is taking us back to look at the app/views/layouts/application.html.erb which i will put below:

So first, parentheses are optional in Ruby. These two are equivalent:

Second, the media argument, while looking like a hash but is missing curly braces. They are also optional in this context. This is a little worrisome, but also makes it look more natural.

Also, the use of the hashrocket is the older syntax. This is used because “‘data-turbolinks-track’ => true” uses hyphens which are invalid.

Yay, time to move on to 4.4 Ruby classes. First, we will look at Constructors.

So, above we see that using the method .class returns the class that s is, which is “String”

We can also use something called a named constructor, here being: String.new(“foobar”) that has the same effect as the literal constructor which is s = “foobar”

This also works with arrays:

There is no reason to do this for strings and arrays.

So, with a hash the Hash.new takes a default value for the hash, which is the value for a nonexistent key. Also, when a method gets called on the class itself, such as the .new method, it is called a class method. A method called on an instance is called an instance method.

Next, let’s look at class inheritance. This is demonstrated here using the .superclass method:

So, with this crude diagram below you will notice that the superclass of STRING is OBJECT and the superclass of OBJECT is BASICOBJECT. This is true of all Ruby objects.

String –> Object –> BasicObject

So now we are going to make our own class with a palindrome? method that returns true if the word is the same forward and backwords!

and let’s give it a try:

So, as seen in the above the method .palindrome will check the string given and see if it is the same forward and backwards. There is, however, a way to do this having our new “Word” class inherit from “String.” The above is creating a class to create a method to then take a string as an argument. The below example shows the inheritance:

And see below that now the new class has inherited all of the methods from String

And we can use the .superclass method on the new class as well.

OK, as much as I wanted to finish Chapter 4 today, I can’t do it! There is a lot of material here, and I want to understand it all. Tomorrow I will be picking up where I left off, looking at 4.4.3 Modifying built-in classes. I am learning a lot and really enjoying myself!