Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:00,000 --> 00:00:10,000
So we've used the each method to iterate through basic Ruby arrays, but what happens when you write your own collection class?
2
00:00:10,000 --> 00:00:12,000
Well, let's look at an example.
3
00:00:12,000 --> 00:00:18,000
Let's say we have a simple genres class that contains an array of genres in the name instance variable.
4
00:00:18,000 --> 00:00:22,000
For our purposes, it's simply a collection of genre names.
5
00:00:22,000 --> 00:00:25,000
Action, comedy, sci-fi, and adventure.
6
00:00:25,000 --> 00:00:29,000
What we want to be able to do is iterate through the names using each.
7
00:00:29,000 --> 00:00:32,000
Sure, so we might think we could just say genres.each.
8
00:00:32,000 --> 00:00:33,000
Give it the block.
9
00:00:33,000 --> 00:00:37,000
This is going to give us the name of the genre, and then we could just print it out like so.
10
00:00:37,000 --> 00:00:43,000
But that's not going to work because genres is an object of the genre's class,
11
00:00:43,000 --> 00:00:46,000
and it doesn't define an each method.
12
00:00:46,000 --> 00:00:49,000
The genre's class has a or contains an array.
13
00:00:49,000 --> 00:00:53,000
That's this names instance variable, and it has an each method,
14
00:00:53,000 --> 00:00:56,000
but we're one level removed from it out here.
15
00:00:56,000 --> 00:00:59,000
But we can define our own each method.
16
00:00:59,000 --> 00:01:02,000
Up inside of our genre's class, we'll just have a method called each.
17
00:01:02,000 --> 00:01:08,000
One way to do this would be to yield each of those things, yield action, yield comedy,
18
00:01:08,000 --> 00:01:11,000
and so on, but that's not going to scale very well.
19
00:01:11,000 --> 00:01:15,000
We're going to have an individual line for each of those names.
20
00:01:15,000 --> 00:01:21,000
So there's a better way to do that, and that's just a piggyback on the each method that the names array already has.
21
00:01:21,000 --> 00:01:27,000
Names isn't array, we can call each on that array, and then it's going to yield to us the name,
22
00:01:27,000 --> 00:01:33,000
and then we can just turn around and yield it to the associated block for the each method,
23
00:01:33,000 --> 00:01:35,000
which is this block down here.
24
00:01:35,000 --> 00:01:41,000
So again, this method is just going to piggyback on the each method that's defined on the names array.
25
00:01:41,000 --> 00:01:45,000
And now when we run this, well it prints out all of our genres.
26
00:01:45,000 --> 00:01:47,000
So when writing your own collection class,
27
00:01:47,000 --> 00:01:52,000
the role of the each method is to yield items to the associated block.
28
00:01:52,000 --> 00:01:54,000
So let's look at another example.
29
00:01:54,000 --> 00:01:56,000
This one will have two classes.
30
00:01:56,000 --> 00:02:00,000
Here we have a movie class with some fairly obvious attributes,
31
00:02:00,000 --> 00:02:03,000
title, rating, and duration time.
32
00:02:03,000 --> 00:02:07,000
When we watch the movie, we print out, watching the name of the movie,
33
00:02:07,000 --> 00:02:09,000
and it's rating and duration in minutes.
34
00:02:09,000 --> 00:02:12,000
For this example, we created four movie objects.
35
00:02:12,000 --> 00:02:19,000
We also have a movie cue class, which serves as a collection of movie objects in an array.
36
00:02:19,000 --> 00:02:23,000
So to add a movie to the cue, we call the add movie method.
37
00:02:23,000 --> 00:02:28,000
For this example, we have a cue named Friday night with three of the four movies.
38
00:02:28,000 --> 00:02:34,000
What we want to be able to do is iterate through the movies in the cue by calling each.
39
00:02:34,000 --> 00:02:37,000
So given our cue object, we want to be able to call each.
40
00:02:37,000 --> 00:02:44,000
We want that to yield a movie object to us, which then we can watch by calling movie.watch.
41
00:02:44,000 --> 00:02:48,000
That's the thing that prints out the movie we're actually watching.
42
00:02:48,000 --> 00:02:51,000
Now we know this won't work because the cue object isn't an array.
43
00:02:51,000 --> 00:02:58,000
It doesn't find a each method, but we can define that each method up in the movie cue class.
44
00:02:58,000 --> 00:03:01,000
All we needed to do is loop through all the movies.
45
00:03:01,000 --> 00:03:06,000
We'll use the each method on the movies array and then yield them in turn.
46
00:03:06,000 --> 00:03:12,000
So this is going to hand us a movie object, which we're just going to turn around and yield to the associated block.
47
00:03:12,000 --> 00:03:18,000
So in the same way we can ask an array for each of the elements, we can now ask a movie cue for each of its movies.
48
00:03:18,000 --> 00:03:22,000
If we run this, we see that we're watching the three movies that are in our cue.
49
00:03:22,000 --> 00:03:27,000
Now what's cool about this is from outside of the class, when we're calling each down here,
50
00:03:27,000 --> 00:03:31,000
we don't care how those movies are stored internally in the class.
51
00:03:31,000 --> 00:03:37,000
I think we stored in the database or off on some web service somewhere. The each method inside of the class
52
00:03:37,000 --> 00:03:44,000
encapsulates all those details, but outside of the class, we don't have to worry about how all those movies are being managed.
53
00:03:44,000 --> 00:03:50,000
We just call each and we know that it's going to yield each movie to us, however they're stored.
54
00:03:50,000 --> 00:03:57,000
Now the convention is to name the most obvious iterator method each, and there's a good reason for that, which we'll see in a minute.
55
00:03:57,000 --> 00:04:03,000
But you can also have other iterator methods, like let's say I only want to watch PG movies.
56
00:04:03,000 --> 00:04:09,000
In addition to our regular each method, we can have another method called each PG movie, for example.
57
00:04:09,000 --> 00:04:11,000
How's that defined?
58
00:04:11,000 --> 00:04:14,000
Each PG movie?
59
00:04:14,000 --> 00:04:19,000
Okay, well what we need to do here is select all the movies that have a rating of PG.
60
00:04:19,000 --> 00:04:23,000
We know how to do that. We can call select on the movies array.
61
00:04:23,000 --> 00:04:28,000
Select all the movies we're rating equals PG.
62
00:04:28,000 --> 00:04:32,000
That's going to return an array, remember, with all those select movies.
63
00:04:32,000 --> 00:04:41,000
We can chain this together with an each, which will go through all those select movies, and then yield them to the associated block.
64
00:04:41,000 --> 00:04:45,000
We run this. We see that we're only watching the PG movies now.
65
00:04:45,000 --> 00:04:50,000
You know, we could make this more generic so that you could watch movies of any rating.
66
00:04:50,000 --> 00:04:57,000
That's true. Instead of using each PG movie, we might call this something like each by rating.
67
00:04:57,000 --> 00:05:01,000
And then just pass in a rating variable, which will substitute in here.
68
00:05:01,000 --> 00:05:04,000
So it's not hard-coded. This would be rating.
69
00:05:04,000 --> 00:05:08,000
And then down here, we'll just call each by rating.
70
00:05:08,000 --> 00:05:11,000
This method takes a parameter, which is the rating we want.
71
00:05:11,000 --> 00:05:18,000
This case will pass in PG, and we get those two movies we had before, or if we just wanted to watch the G movies.
72
00:05:18,000 --> 00:05:20,000
We've got one G movie in our queue.
73
00:05:20,000 --> 00:05:27,000
So Mike mentioned earlier that you want to name your most common iterator each, and there's really a good reason for that.
74
00:05:27,000 --> 00:05:33,000
Yeah, it turns out that by defining an each method, you unlock all the behavior in the numeral module.
75
00:05:33,000 --> 00:05:37,000
So let's say we want to find all the long movies in our queue.
76
00:05:37,000 --> 00:05:43,000
All right, let's just add a little space down here. We want all the long movies. Long movies.
77
00:05:43,000 --> 00:05:49,000
We'd like to be able to do this. Take our queue object and call select and select all the movies.
78
00:05:49,000 --> 00:05:56,000
Remember, it yields movies to us. Select all the movies in the queue whose duration is greater than 100 minutes, for example.
79
00:05:56,000 --> 00:05:59,000
And then we could print out long movies.
80
00:05:59,000 --> 00:06:03,000
But that's not going to work because the queue class doesn't define the select method.
81
00:06:03,000 --> 00:06:10,000
Remember, the select method can only be called on a raise, or we've only seen it being called on a raise so far.
82
00:06:10,000 --> 00:06:15,000
But it turns out that the select method isn't actually defined in the array class.
83
00:06:15,000 --> 00:06:18,000
It's defined in the enumerable module.
84
00:06:18,000 --> 00:06:23,000
The array class includes this module, which is why it works for arrays.
85
00:06:23,000 --> 00:06:32,000
We can make it work for our movie queue class simply by including that enumerable module, which we'll do up above here and movie queue.
86
00:06:32,000 --> 00:06:36,000
We say include enumerable.
87
00:06:36,000 --> 00:06:41,000
Now all the methods defined in enumerable are defined in our movie queue class.
88
00:06:41,000 --> 00:06:47,000
So now we see that it's selected the long movie in the queue, the one that had a duration in this case, it was 140.
89
00:06:47,000 --> 00:06:49,000
It was greater than 100 minutes.
90
00:06:49,000 --> 00:06:55,000
So why does it work? Well, there's actually two reasons. The first is that we include the enumerable module.
91
00:06:55,000 --> 00:07:02,000
But the enumerable module requires that the host class, which is the class that we included in our movie queue class,
92
00:07:02,000 --> 00:07:08,000
it must define an each method, and we've defined an each method here that yields all the movies.
93
00:07:08,000 --> 00:07:14,000
So just to prove this, I'm going to comment out the each method here and try to run this again.
94
00:07:14,000 --> 00:07:20,000
And this time we get an error that the top is select undefined method each for a movie queue.
95
00:07:20,000 --> 00:07:24,000
So clearly the select method is trying to call the each method.
96
00:07:24,000 --> 00:07:31,000
And just to prove that, well, uncomment this, I'm going to change this to a multi-line block because I want to print something out.
97
00:07:31,000 --> 00:07:41,000
We yield the movie there. But right here, I just want to print out yielding the movie title.
98
00:07:41,000 --> 00:07:46,000
Just like that. So we've got an each method defined with a little bit of debugging inside of there.
99
00:07:46,000 --> 00:07:52,000
If we run this now, we'll notice we watch the movie, but then we yield the three movies.
100
00:07:52,000 --> 00:08:00,000
Toy Story cast away in Apollo 13. The select method then has a look at those movies, how the criteria is defined in the block.
101
00:08:00,000 --> 00:08:05,000
And then it selects the one that matches the block criteria. In this case, it's Apollo 13.
102
00:08:05,000 --> 00:08:12,000
So we see that the each method is being called here as a byproduct of calling the select method here.
103
00:08:12,000 --> 00:08:20,000
So if you define an each method and include or mix in a new normal in your class, then all the new normal methods are unlocked.
104
00:08:20,000 --> 00:08:26,000
So this means we could find the first movie with the number 13 in the title using the detect method.
105
00:08:26,000 --> 00:08:31,000
Sure, all those methods are at our disposal. We could call Q dot detect.
106
00:08:31,000 --> 00:08:35,000
That's going to give us a movie object because remember the Q yields movies.
107
00:08:35,000 --> 00:08:41,000
We want the title and I'll use a regular expression match here equal tilde in Ruby.
108
00:08:41,000 --> 00:08:47,000
And the regular expression is going to be 13. So any movie whose title contains 13.
109
00:08:47,000 --> 00:08:52,000
We want to detect that and then I'll just print it out using the P method here.
110
00:08:52,000 --> 00:08:57,000
Right? Run that and we see we get back Apollo 13.
111
00:08:57,000 --> 00:09:08,000
So let's recap. Our movie Q class is a collection of movie objects. For example, we could have a family movie Q with any number of movies and a drama movie Q with movies.
112
00:09:08,000 --> 00:09:14,000
If we want to iterate through the collection of movies, we can't call each like so outside the class.
113
00:09:14,000 --> 00:09:18,000
The movie Q objects themselves aren't array objects.
114
00:09:18,000 --> 00:09:26,000
A movie Q object contains an array of its movies, but outside the class were one level we move from that array.
115
00:09:26,000 --> 00:09:34,000
So we need to define an each method in the movie Q class that loops through all the objects in the movies array and yields each one in turn.
116
00:09:34,000 --> 00:09:44,000
Now when we run this line of code, it calls the each method defined in the movie Q class and the block does whatever once with each yielded movie object.
117
00:09:44,000 --> 00:09:52,000
We run into a similar problem if we try to select certain movies from a movie Q or use any of the a new mobile methods.
118
00:09:52,000 --> 00:10:02,000
But if we include the a new mobile module and have our own each method defined, then we can use any of the a new mobile methods on the movie Q object. Pretty cool, huh?
119
00:10:02,000 --> 00:10:06,000
In the exercise, we're going to give you a chance to try all this on a different set of classes.
120
00:10:06,000 --> 00:10:11,000
And in the next section, we'll show you how the a new mobile module actually works.
121
00:10:11,000 --> 00:10:15,000
See you then.
14037
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.