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:07,760
So in the last section, we looked at how to use the each method to iterate through our order
2
00:00:07,760 --> 00:00:08,760
objects.
3
00:00:08,760 --> 00:00:12,120
But now let's see if we want to do something different, like we want to separate the big
4
00:00:12,120 --> 00:00:16,160
orders from the small orders or we only want to select certain orders.
5
00:00:16,160 --> 00:00:21,320
Yeah, it's so common to want to do this that Ruby gives us methods for processing collections
6
00:00:21,320 --> 00:00:23,040
in a variety of different ways.
7
00:00:23,040 --> 00:00:28,400
And this is a great opportunity to practice calling methods that take blocks.
8
00:00:28,400 --> 00:00:33,600
So to make this a little more interesting, we extended the order class ever so slightly.
9
00:00:33,600 --> 00:00:37,239
The tax table is now in the constant tax table.
10
00:00:37,239 --> 00:00:40,839
And we added some new attributes, state and status.
11
00:00:40,839 --> 00:00:45,120
We also changed the initialize method to take these new attributes and we changed the order
12
00:00:45,120 --> 00:00:46,120
just slightly.
13
00:00:46,120 --> 00:00:50,480
Which should also point out that the default status is pending.
14
00:00:50,480 --> 00:00:56,599
We've then defined a tax method that calculates the tax based on the state and the total.
15
00:00:56,600 --> 00:01:01,160
And we changed the two S method to include all of our new attributes.
16
00:01:01,160 --> 00:01:06,360
We also created a few example orders in an array, but not using the Times method.
17
00:01:06,360 --> 00:01:09,240
We used explicit attributes this time.
18
00:01:09,240 --> 00:01:12,120
We also print out all the orders using putas.
19
00:01:12,120 --> 00:01:13,160
So let's run it.
20
00:01:13,160 --> 00:01:14,160
Sure.
21
00:01:14,160 --> 00:01:18,640
And remember, putas is going to call the two S method on all the orders in the array.
22
00:01:18,640 --> 00:01:20,320
We have a new two S method here.
23
00:01:20,320 --> 00:01:24,680
So we see we've got the customers email, their state, the total of the order, and then
24
00:01:24,680 --> 00:01:25,680
the status.
25
00:01:25,680 --> 00:01:26,680
All right.
26
00:01:26,680 --> 00:01:29,600
So let's say we want to generate a sales report for our orders.
27
00:01:29,600 --> 00:01:32,160
And we want to print out all the large orders.
28
00:01:32,160 --> 00:01:33,160
Sure.
29
00:01:33,160 --> 00:01:35,840
Let's make a little space down here.
30
00:01:35,840 --> 00:01:36,840
And I'm going to put a label.
31
00:01:36,840 --> 00:01:38,720
This is going to be our big orders.
32
00:01:38,720 --> 00:01:42,480
And we're going to take our orders array.
33
00:01:42,480 --> 00:01:47,560
And what we basically want to do here is select all the orders that have a total greater
34
00:01:47,560 --> 00:01:50,720
than or equal to $300 as a total.
35
00:01:50,720 --> 00:01:53,520
Well, there's a method called select.
36
00:01:53,520 --> 00:01:54,840
It takes a block.
37
00:01:54,840 --> 00:01:59,520
It's going to hand the block as a block parameter the next order in the array.
38
00:01:59,520 --> 00:02:04,960
And now we need to tell select how to determine whether to select that order or not.
39
00:02:04,960 --> 00:02:11,120
So the way we do that is we're going to say, oh, dot total is greater than or equal to $300.
40
00:02:11,120 --> 00:02:14,280
That expression is going to return true or false.
41
00:02:14,280 --> 00:02:18,120
If it's true, then select knows to go ahead and select that order.
42
00:02:18,120 --> 00:02:21,440
If it's false, then it says, oh, it shouldn't be selected.
43
00:02:21,440 --> 00:02:27,040
So when it returns true and it selects an order, instead of changing the original array,
44
00:02:27,040 --> 00:02:31,359
which would be orders here, it actually creates a new array and returns that new array,
45
00:02:31,359 --> 00:02:33,440
which contains all the selected orders.
46
00:02:33,440 --> 00:02:37,359
So I'm going to actually assign this to a variable called big orders.
47
00:02:37,359 --> 00:02:38,600
It's going to be a new array.
48
00:02:38,600 --> 00:02:43,000
And then down below here, I'm going to print out what's in that big orders array using
49
00:02:43,000 --> 00:02:44,560
put us.
50
00:02:44,560 --> 00:02:47,520
Now if we run this, we see under big orders.
51
00:02:47,520 --> 00:02:51,640
We've only got the orders that have a total greater than or equal to $300.
52
00:02:51,640 --> 00:02:57,480
So only the orders were the block here returned true are going to be put in that new big
53
00:02:57,480 --> 00:02:58,480
orders array.
54
00:02:58,480 --> 00:03:02,400
Now it's important to note that this didn't change our original orders array.
55
00:03:02,400 --> 00:03:05,760
In fact, if I just print out, I'll just put a little marker right there.
56
00:03:05,760 --> 00:03:10,200
And I print our original orders, which is in the orders array, well, we see we still have
57
00:03:10,200 --> 00:03:12,920
the four orders that we started with.
58
00:03:12,920 --> 00:03:19,440
So this select method returned a new array, which we assigned to big orders.
59
00:03:19,440 --> 00:03:21,560
Now here's a little gotcha, and I'm going to clean this up.
60
00:03:21,560 --> 00:03:22,959
I don't want to see the original orders.
61
00:03:22,959 --> 00:03:25,239
I just want to focus in on this select.
62
00:03:25,239 --> 00:03:28,720
Sometimes when you're using one of these methods like this, you might want to add a little
63
00:03:28,720 --> 00:03:29,720
bit of debugging.
64
00:03:29,720 --> 00:03:34,119
You put something like a puttess inside of here because you want to see what this expression
65
00:03:34,119 --> 00:03:36,519
evaluates to either true or false.
66
00:03:36,519 --> 00:03:38,839
So you put a puttess inside of there.
67
00:03:38,840 --> 00:03:43,200
If we run this, what happens is to put us prints the expression, what the expression
68
00:03:43,200 --> 00:03:46,080
returned true, true, false false in this case.
69
00:03:46,080 --> 00:03:49,640
But notice that we don't get our big orders array down here.
70
00:03:49,640 --> 00:03:52,040
There's nothing in the big orders array.
71
00:03:52,040 --> 00:03:56,720
In fact, I can demonstrate that by using the P method on big orders.
72
00:03:56,720 --> 00:04:00,480
And that's just going to show us the internal representation of that array.
73
00:04:00,480 --> 00:04:01,760
I run it this time.
74
00:04:01,760 --> 00:04:04,440
You see the array is empty.
75
00:04:04,440 --> 00:04:05,600
What happened here?
76
00:04:05,600 --> 00:04:09,480
So we know that this evaluated true for some of the orders.
77
00:04:09,480 --> 00:04:12,480
But the problem is the puttess statement.
78
00:04:12,480 --> 00:04:17,760
Once it's printed out, whatever message that should print out to the console, it returns
79
00:04:17,760 --> 00:04:18,760
nil.
80
00:04:18,760 --> 00:04:20,920
Nil in Ruby is false.
81
00:04:20,920 --> 00:04:26,760
So the last expression evaluated in this block returns nil because puttess returns nil.
82
00:04:26,760 --> 00:04:27,920
Nil is false.
83
00:04:27,920 --> 00:04:32,640
So therefore the select method says, oh, I shouldn't select any of these orders at all.
84
00:04:32,640 --> 00:04:35,680
And that's why we end up with an empty array big orders.
85
00:04:35,680 --> 00:04:36,880
So it's just a gotcha.
86
00:04:36,880 --> 00:04:40,800
Sometimes when you put in these debugging statements like this, you can end up changing
87
00:04:40,800 --> 00:04:46,000
the behavior of the block and get some unintended consequences.
88
00:04:46,000 --> 00:04:48,479
I want to point out a second gotcha here.
89
00:04:48,479 --> 00:04:51,320
And that's sometimes you don't assign these to variables at all.
90
00:04:51,320 --> 00:04:54,880
You might just want to do a puttess right here because you just want to print out the
91
00:04:54,880 --> 00:04:57,960
result not stored in a temporary variable.
92
00:04:57,960 --> 00:05:00,400
Well, this will work just as you expect.
93
00:05:00,400 --> 00:05:04,960
Our big orders, we've got two of those orders down here, the ones we expect.
94
00:05:04,960 --> 00:05:09,960
But let's now say you changed this around to use the do-end style of blocks.
95
00:05:09,960 --> 00:05:12,520
All right, just like that.
96
00:05:12,520 --> 00:05:16,080
If you run this, you get something totally different.
97
00:05:16,080 --> 00:05:18,560
The output is this enumerator.
98
00:05:18,560 --> 00:05:20,560
Why is that?
99
00:05:20,560 --> 00:05:21,919
Well, here's what happens.
100
00:05:21,919 --> 00:05:26,799
There is a slight difference between using curly braces and using do-end.
101
00:05:26,800 --> 00:05:30,840
Basically, the curly braces bind tighter than do-end.
102
00:05:30,840 --> 00:05:34,560
Do-end in this case, don't get applied to the select method.
103
00:05:34,560 --> 00:05:41,400
Instead, what happens is, as Ruby is evaluating this code, it takes the puttess and it
104
00:05:41,400 --> 00:05:45,600
is going to print the return value of select here.
105
00:05:45,600 --> 00:05:48,720
Then after it does that, then it has a look at this block.
106
00:05:48,720 --> 00:05:53,520
Well, that's not what we want because select without a block returns the numerator,
107
00:05:53,520 --> 00:05:56,600
which in this case is what puttess prints out.
108
00:05:56,600 --> 00:06:01,800
But then puttess doesn't care if we associate a block with it, it just basically ignores
109
00:06:01,800 --> 00:06:02,800
the block.
110
00:06:02,800 --> 00:06:07,640
So the block isn't getting associated with the select method in this case.
111
00:06:07,640 --> 00:06:10,240
It's getting associated with the puttess method.
112
00:06:10,240 --> 00:06:15,160
So there's a little bit of a precedence difference between curly braces and do-end.
113
00:06:15,160 --> 00:06:18,760
This won't often bite you, but it's just something to be aware of.
114
00:06:18,760 --> 00:06:23,120
In this particular case, I'm just going to change it back to the single line form, because
115
00:06:23,120 --> 00:06:25,120
we've just got a single line of Ruby code here.
116
00:06:25,120 --> 00:06:28,920
Give us a little extra space, just like that.
117
00:06:28,920 --> 00:06:34,360
And then in this form, the block here is going to bind to the select method.
118
00:06:34,360 --> 00:06:40,000
So all this is going to run, return an array, and then puttess is going to print out the
119
00:06:40,000 --> 00:06:43,240
result of that, which is exactly what we want.
120
00:06:43,240 --> 00:06:46,720
So here's a slow motion replay of how the select method works.
121
00:06:46,720 --> 00:06:48,680
We have our array of orders.
122
00:06:48,680 --> 00:06:50,560
What do we want to do with them?
123
00:06:50,560 --> 00:06:53,800
First we want to filter orders that meet a certain criteria.
124
00:06:53,800 --> 00:06:56,320
So we use the select method.
125
00:06:56,320 --> 00:07:00,480
Select expects an associated block that defines the selection criteria.
126
00:07:00,480 --> 00:07:05,480
We want to select only those orders with a total greater than or equal to 300.
127
00:07:05,480 --> 00:07:10,280
Select will return a new array that contains all the matching orders, or an empty array
128
00:07:10,280 --> 00:07:12,480
if there are no matching orders.
129
00:07:12,480 --> 00:07:16,120
We assign the new array to the variable big orders.
130
00:07:16,120 --> 00:07:20,840
When this code runs, the select method, similar to the each method, iterates through
131
00:07:20,840 --> 00:07:24,280
each element in the array and passes it to the block.
132
00:07:24,280 --> 00:07:28,479
So the first time through the iteration, our block gets mows order.
133
00:07:28,479 --> 00:07:31,880
The total is 300, so his order is a match.
134
00:07:31,880 --> 00:07:36,520
The comparison evaluates to true, which is returned from the block.
135
00:07:36,520 --> 00:07:41,760
Given this return value, the select method adds mows order to the new array.
136
00:07:41,760 --> 00:07:46,400
Larry's order is also match, so the return value of the block is again true, and his
137
00:07:46,400 --> 00:07:48,679
order is added to the array.
138
00:07:48,680 --> 00:07:51,880
So last two orders don't meet the selection criteria.
139
00:07:51,880 --> 00:07:55,680
The block returns faults for these orders, and therefore they aren't added to the new
140
00:07:55,680 --> 00:07:56,880
array.
141
00:07:56,880 --> 00:08:01,520
So our final big orders array contains the two selected orders.
142
00:08:01,520 --> 00:08:05,320
You may see the synonym find-all used in place of select.
143
00:08:05,320 --> 00:08:07,920
Both methods do the same thing.
144
00:08:07,920 --> 00:08:10,440
So you might be wondering, what about small orders?
145
00:08:10,440 --> 00:08:13,360
Well, there's another method for that.
146
00:08:13,360 --> 00:08:15,360
So we want to print out all the small orders.
147
00:08:15,360 --> 00:08:19,920
Put a little label here, small orders, and it turns out that in this case we're going
148
00:08:19,920 --> 00:08:20,920
to use the same block.
149
00:08:20,920 --> 00:08:23,520
So I'm just going to go ahead and copy that block.
150
00:08:23,520 --> 00:08:25,400
But we're going to use a different method.
151
00:08:25,400 --> 00:08:27,880
We're going to use the reject method.
152
00:08:27,880 --> 00:08:31,920
Now reject is similar to select, but instead of selecting the orders, it's actually going
153
00:08:31,920 --> 00:08:35,400
to take some criteria for which orders it should reject.
154
00:08:35,400 --> 00:08:37,800
So I'm going to pass it the same block.
155
00:08:37,800 --> 00:08:42,200
We want to reject all the orders who have a total greater than or equal to 300.
156
00:08:42,200 --> 00:08:44,840
Similar to select, it returns a new array.
157
00:08:44,840 --> 00:08:50,800
So we'll assign this to a small orders variable, and then we'll just print out small orders,
158
00:08:50,800 --> 00:08:52,120
just like that.
159
00:08:52,120 --> 00:08:57,400
If we run that, we get the other two orders, all the orders less than 300.
160
00:08:57,400 --> 00:09:01,120
As Mike pointed out, reject is the opposite of select.
161
00:09:01,120 --> 00:09:04,400
So when most order is evaluated, the block returns true.
162
00:09:04,400 --> 00:09:07,960
His order is greater than or equal to 300.
163
00:09:07,960 --> 00:09:11,080
Therefore, the reject method, well, rejects it.
164
00:09:11,080 --> 00:09:13,560
It is not added to the new array.
165
00:09:13,560 --> 00:09:15,560
The same thing happens for Larry's order.
166
00:09:15,560 --> 00:09:17,199
It's rejected as well.
167
00:09:17,199 --> 00:09:22,079
For curly's order, the block returns false, so it is not rejected.
168
00:09:22,079 --> 00:09:26,119
Instead, it's added to the new array along with Shem's order.
169
00:09:26,119 --> 00:09:31,280
So our final small order array contains the two orders whose total is not greater than
170
00:09:31,280 --> 00:09:34,000
or equal to 300.
171
00:09:34,000 --> 00:09:38,719
So the warehouse just called, and they want to know if any orders are pending.
172
00:09:38,719 --> 00:09:39,719
Well, we can do that.
173
00:09:39,720 --> 00:09:43,840
All right, I'm just going to create some more space down here for us to play around here.
174
00:09:43,840 --> 00:09:46,440
And they want to know if any orders are pending.
175
00:09:46,440 --> 00:09:48,280
Well, take our array.
176
00:09:48,280 --> 00:09:50,800
There's an any question mark method here.
177
00:09:50,800 --> 00:09:52,080
Question mark methods in Ruby.
178
00:09:52,080 --> 00:09:54,920
Generally, your turn tour false, like we're asking it.
179
00:09:54,920 --> 00:09:55,920
Well, a question.
180
00:09:55,920 --> 00:09:57,640
It takes a block.
181
00:09:57,640 --> 00:10:02,560
It's going to pass us all the orders in turn, and then we give it criteria for finding
182
00:10:02,560 --> 00:10:05,240
whether there are any orders matching that criteria.
183
00:10:05,240 --> 00:10:10,000
We want to know if we have an order whose status is equal to pending.
184
00:10:10,000 --> 00:10:14,040
We use the symbol to represent the status of those orders.
185
00:10:14,040 --> 00:10:16,760
And then that's going to actually return tour or false.
186
00:10:16,760 --> 00:10:20,680
We can assign it to a variable here, but I'm just going to print it out using put us like
187
00:10:20,680 --> 00:10:21,680
that.
188
00:10:21,680 --> 00:10:24,920
So any question mark is going to pass each element to the block.
189
00:10:24,920 --> 00:10:30,600
If the block returns any value other than false or nil, then the method itself returns
190
00:10:30,600 --> 00:10:33,280
true, and it stops calling the block.
191
00:10:33,280 --> 00:10:34,600
So we run that.
192
00:10:34,600 --> 00:10:36,959
We see that it prints out true.
193
00:10:36,959 --> 00:10:38,560
There is a pending order.
194
00:10:38,560 --> 00:10:41,800
So then what is that first pending order?
195
00:10:41,800 --> 00:10:44,120
Well, we need to use a different method for that.
196
00:10:44,120 --> 00:10:47,880
We want to find the specific order, the first order that's pending.
197
00:10:47,880 --> 00:10:49,680
So we take our array orders.
198
00:10:49,680 --> 00:10:51,920
The method this time is called detect.
199
00:10:51,920 --> 00:10:54,120
We want to detect an order.
200
00:10:54,120 --> 00:10:55,400
Here's our block parameter.
201
00:10:55,400 --> 00:10:58,920
We want the order whose status is equal to pending.
202
00:10:58,920 --> 00:11:01,319
It's the same block we used for any.
203
00:11:01,320 --> 00:11:05,200
In this time, instead of getting back a true or false value, we actually get back
204
00:11:05,200 --> 00:11:08,840
the order, the first order that matches that criteria.
205
00:11:08,840 --> 00:11:14,000
So I'll assign it to a variable called order, and then we'll just print out the order there.
206
00:11:14,000 --> 00:11:18,160
And the last order, or actually the first order that's pending, is customer once order,
207
00:11:18,160 --> 00:11:20,520
which we see right here.
208
00:11:20,520 --> 00:11:23,560
So what if we want to see if any order has been completed?
209
00:11:23,560 --> 00:11:28,440
We'd use the any question mark method with a block that checks for a completed status.
210
00:11:28,440 --> 00:11:31,760
It passes each order in the collection to the block.
211
00:11:31,760 --> 00:11:36,320
Moes order is pending, so the block returns false and moves to Larry's order.
212
00:11:36,320 --> 00:11:40,760
Larry's order on the other hand is completed, so the block returns true.
213
00:11:40,760 --> 00:11:45,800
If the block returns a true value, any value other than false or no, then the method
214
00:11:45,800 --> 00:11:49,040
returns true and stops calling the block.
215
00:11:49,040 --> 00:11:54,520
If, however, all the orders are pending, and therefore none of the orders match the criteria,
216
00:11:54,520 --> 00:12:00,040
then the block returns false for all the orders and the method itself returns false.
217
00:12:00,040 --> 00:12:03,199
What if we want to find the first order that meets a certain criteria?
218
00:12:03,199 --> 00:12:06,000
Say, the first order from Colorado.
219
00:12:06,000 --> 00:12:07,840
We'd use the detect method.
220
00:12:07,840 --> 00:12:12,280
It returns the first order in the collection that matches the criteria and the block.
221
00:12:12,280 --> 00:12:18,199
Cruelys order, or set another way, when the block returns a true value, it stops and doesn't
222
00:12:18,199 --> 00:12:20,160
look any further.
223
00:12:20,160 --> 00:12:23,520
Now something really cool is happening behind the scenes here.
224
00:12:23,520 --> 00:12:28,720
The array and hash classes define their own each methods, which we used earlier.
225
00:12:28,720 --> 00:12:33,439
We've seen that we can also call select, reject, and friends on arrays.
226
00:12:33,439 --> 00:12:37,040
But those methods aren't actually defined in the array class.
227
00:12:37,040 --> 00:12:42,640
Instead they're defined in the innumerable module, so they can be shared across classes.
228
00:12:42,640 --> 00:12:49,880
In particular, both the array and hash classes include, or mix in, the innumerable module.
229
00:12:49,880 --> 00:12:53,439
So it's as if these methods are defined in both classes.
230
00:12:53,440 --> 00:12:57,560
Now this is really powerful, and we'll see how to mix these innumerable methods into your
231
00:12:57,560 --> 00:12:59,760
own classes a bit later.
232
00:12:59,760 --> 00:13:04,400
These innumerable methods are big time saver, and you'll see them used all over in Ruby
233
00:13:04,400 --> 00:13:05,400
and Rails.
234
00:13:05,400 --> 00:13:08,440
So before moving on, take a couple minutes to practice with them.
235
00:13:08,440 --> 00:13:12,120
And in the next section, we'll look at a few more of these innumerable methods that save
236
00:13:12,120 --> 00:13:13,600
us a bunch of time.
237
00:13:13,600 --> 00:13:16,080
See you then.
238
00:13:16,080 --> 00:13:19,080
These innumerable methods are a big time saver.
239
00:13:19,080 --> 00:13:36,200
Ag iron exists.
21695
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.