Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranî)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
So in the last section, we looked at how to use the each method to iterate through our order
objects.
But now let's see if we want to do something different, like we want to separate the big
orders from the small orders or we only want to select certain orders.
Yeah, it's so common to want to do this that Ruby gives us methods for processing collections
in a variety of different ways.
And this is a great opportunity to practice calling methods that take blocks.
So to make this a little more interesting, we extended the order class ever so slightly.
The tax table is now in the constant tax table.
And we added some new attributes, state and status.
We also changed the initialize method to take these new attributes and we changed the order
just slightly.
Which should also point out that the default status is pending.
We've then defined a tax method that calculates the tax based on the state and the total.
And we changed the two S method to include all of our new attributes.
We also created a few example orders in an array, but not using the Times method.
We used explicit attributes this time.
We also print out all the orders using putas.
So let's run it.
Sure.
And remember, putas is going to call the two S method on all the orders in the array.
We have a new two S method here.
So we see we've got the customers email, their state, the total of the order, and then
the status.
All right.
So let's say we want to generate a sales report for our orders.
And we want to print out all the large orders.
Sure.
Let's make a little space down here.
And I'm going to put a label.
This is going to be our big orders.
And we're going to take our orders array.
And what we basically want to do here is select all the orders that have a total greater
than or equal to $300 as a total.
Well, there's a method called select.
It takes a block.
It's going to hand the block as a block parameter the next order in the array.
And now we need to tell select how to determine whether to select that order or not.
So the way we do that is we're going to say, oh, dot total is greater than or equal to $300.
That expression is going to return true or false.
If it's true, then select knows to go ahead and select that order.
If it's false, then it says, oh, it shouldn't be selected.
So when it returns true and it selects an order, instead of changing the original array,
which would be orders here, it actually creates a new array and returns that new array,
which contains all the selected orders.
So I'm going to actually assign this to a variable called big orders.
It's going to be a new array.
And then down below here, I'm going to print out what's in that big orders array using
put us.
Now if we run this, we see under big orders.
We've only got the orders that have a total greater than or equal to $300.
So only the orders were the block here returned true are going to be put in that new big
orders array.
Now it's important to note that this didn't change our original orders array.
In fact, if I just print out, I'll just put a little marker right there.
And I print our original orders, which is in the orders array, well, we see we still have
the four orders that we started with.
So this select method returned a new array, which we assigned to big orders.
Now here's a little gotcha, and I'm going to clean this up.
I don't want to see the original orders.
I just want to focus in on this select.
Sometimes when you're using one of these methods like this, you might want to add a little
bit of debugging.
You put something like a puttess inside of here because you want to see what this expression
evaluates to either true or false.
So you put a puttess inside of there.
If we run this, what happens is to put us prints the expression, what the expression
returned true, true, false false in this case.
But notice that we don't get our big orders array down here.
There's nothing in the big orders array.
In fact, I can demonstrate that by using the P method on big orders.
And that's just going to show us the internal representation of that array.
I run it this time.
You see the array is empty.
What happened here?
So we know that this evaluated true for some of the orders.
But the problem is the puttess statement.
Once it's printed out, whatever message that should print out to the console, it returns
nil.
Nil in Ruby is false.
So the last expression evaluated in this block returns nil because puttess returns nil.
Nil is false.
So therefore the select method says, oh, I shouldn't select any of these orders at all.
And that's why we end up with an empty array big orders.
So it's just a gotcha.
Sometimes when you put in these debugging statements like this, you can end up changing
the behavior of the block and get some unintended consequences.
I want to point out a second gotcha here.
And that's sometimes you don't assign these to variables at all.
You might just want to do a puttess right here because you just want to print out the
result not stored in a temporary variable.
Well, this will work just as you expect.
Our big orders, we've got two of those orders down here, the ones we expect.
But let's now say you changed this around to use the do-end style of blocks.
All right, just like that.
If you run this, you get something totally different.
The output is this enumerator.
Why is that?
Well, here's what happens.
There is a slight difference between using curly braces and using do-end.
Basically, the curly braces bind tighter than do-end.
Do-end in this case, don't get applied to the select method.
Instead, what happens is, as Ruby is evaluating this code, it takes the puttess and it
is going to print the return value of select here.
Then after it does that, then it has a look at this block.
Well, that's not what we want because select without a block returns the numerator,
which in this case is what puttess prints out.
But then puttess doesn't care if we associate a block with it, it just basically ignores
the block.
So the block isn't getting associated with the select method in this case.
It's getting associated with the puttess method.
So there's a little bit of a precedence difference between curly braces and do-end.
This won't often bite you, but it's just something to be aware of.
In this particular case, I'm just going to change it back to the single line form, because
we've just got a single line of Ruby code here.
Give us a little extra space, just like that.
And then in this form, the block here is going to bind to the select method.
So all this is going to run, return an array, and then puttess is going to print out the
result of that, which is exactly what we want.
So here's a slow motion replay of how the select method works.
We have our array of orders.
What do we want to do with them?
First we want to filter orders that meet a certain criteria.
So we use the select method.
Select expects an associated block that defines the selection criteria.
We want to select only those orders with a total greater than or equal to 300.
Select will return a new array that contains all the matching orders, or an empty array
if there are no matching orders.
We assign the new array to the variable big orders.
When this code runs, the select method, similar to the each method, iterates through
each element in the array and passes it to the block.
So the first time through the iteration, our block gets mows order.
The total is 300, so his order is a match.
The comparison evaluates to true, which is returned from the block.
Given this return value, the select method adds mows order to the new array.
Larry's order is also match, so the return value of the block is again true, and his
order is added to the array.
So last two orders don't meet the selection criteria.
The block returns faults for these orders, and therefore they aren't added to the new
array.
So our final big orders array contains the two selected orders.
You may see the synonym find-all used in place of select.
Both methods do the same thing.
So you might be wondering, what about small orders?
Well, there's another method for that.
So we want to print out all the small orders.
Put a little label here, small orders, and it turns out that in this case we're going
to use the same block.
So I'm just going to go ahead and copy that block.
But we're going to use a different method.
We're going to use the reject method.
Now reject is similar to select, but instead of selecting the orders, it's actually going
to take some criteria for which orders it should reject.
So I'm going to pass it the same block.
We want to reject all the orders who have a total greater than or equal to 300.
Similar to select, it returns a new array.
So we'll assign this to a small orders variable, and then we'll just print out small orders,
just like that.
If we run that, we get the other two orders, all the orders less than 300.
As Mike pointed out, reject is the opposite of select.
So when most order is evaluated, the block returns true.
His order is greater than or equal to 300.
Therefore, the reject method, well, rejects it.
It is not added to the new array.
The same thing happens for Larry's order.
It's rejected as well.
For curly's order, the block returns false, so it is not rejected.
Instead, it's added to the new array along with Shem's order.
So our final small order array contains the two orders whose total is not greater than
or equal to 300.
So the warehouse just called, and they want to know if any orders are pending.
Well, we can do that.
All right, I'm just going to create some more space down here for us to play around here.
And they want to know if any orders are pending.
Well, take our array.
There's an any question mark method here.
Question mark methods in Ruby.
Generally, your turn tour false, like we're asking it.
Well, a question.
It takes a block.
It's going to pass us all the orders in turn, and then we give it criteria for finding
whether there are any orders matching that criteria.
We want to know if we have an order whose status is equal to pending.
We use the symbol to represent the status of those orders.
And then that's going to actually return tour or false.
We can assign it to a variable here, but I'm just going to print it out using put us like
that.
So any question mark is going to pass each element to the block.
If the block returns any value other than false or nil, then the method itself returns
true, and it stops calling the block.
So we run that.
We see that it prints out true.
There is a pending order.
So then what is that first pending order?
Well, we need to use a different method for that.
We want to find the specific order, the first order that's pending.
So we take our array orders.
The method this time is called detect.
We want to detect an order.
Here's our block parameter.
We want the order whose status is equal to pending.
It's the same block we used for any.
In this time, instead of getting back a true or false value, we actually get back
the order, the first order that matches that criteria.
So I'll assign it to a variable called order, and then we'll just print out the order there.
And the last order, or actually the first order that's pending, is customer once order,
which we see right here.
So what if we want to see if any order has been completed?
We'd use the any question mark method with a block that checks for a completed status.
It passes each order in the collection to the block.
Moes order is pending, so the block returns false and moves to Larry's order.
Larry's order on the other hand is completed, so the block returns true.
If the block returns a true value, any value other than false or no, then the method
returns true and stops calling the block.
If, however, all the orders are pending, and therefore none of the orders match the criteria,
then the block returns false for all the orders and the method itself returns false.
What if we want to find the first order that meets a certain criteria?
Say, the first order from Colorado.
We'd use the detect method.
It returns the first order in the collection that matches the criteria and the block.
Cruelys order, or set another way, when the block returns a true value, it stops and doesn't
look any further.
Now something really cool is happening behind the scenes here.
The array and hash classes define their own each methods, which we used earlier.
We've seen that we can also call select, reject, and friends on arrays.
But those methods aren't actually defined in the array class.
Instead they're defined in the innumerable module, so they can be shared across classes.
In particular, both the array and hash classes include, or mix in, the innumerable module.
So it's as if these methods are defined in both classes.
Now this is really powerful, and we'll see how to mix these innumerable methods into your
own classes a bit later.
These innumerable methods are big time saver, and you'll see them used all over in Ruby
and Rails.
So before moving on, take a couple minutes to practice with them.
And in the next section, we'll look at a few more of these innumerable methods that save
us a bunch of time.
See you then.
These innumerable methods are a big time saver.
Ag iron exists.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.