All language subtitles for pragstudio-ruby-19-io (Transcribed on 27-Apr-2023 20-38-13)

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified) Download
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

Hey Mike, we've received a few feature requests for our game.

Oh yeah?

Yeah.

Get me.

Alright, so Mo sent an email.

He said, if I want to vary the number of rounds to the game, I have to change the Ruby code.

And I'd like to be able to specify the number of rounds from the command line.

Oh, that sounds like a good idea.

Yeah, yeah, okay.

Now Larry's cousin tweets.

Wait, Larry's cousin's on Twitter?

Okay.

Okay.

Alright, Larry's cousin tweets, I would like to play the game with different players.

Does he not get along with Mo and Curly?

Yeah, I don't know.

Okay, alright.

But I don't know a smidgen of Ruby.

Well, unfortunately he hasn't taken this fine Ruby course, but you know, we could probably

put all the players in a file and then read from that file.

Okay, alright.

Alright, and then Curly writes us.

Curly says, I want to be able to save off the high scores and email them to my buddies.

But only when he wins, of course.

Oh, of course.

Well, I mean, these are all typical requests you would get for any Ruby program.

In fact, our movie app could use some of these requests.

So let's just start with the command line input part of it.

So back in our flix.rb file here of our movie app, what we'd really like to do is instead

of hard coding this number of plays to a three, we want to take this as command line input.

So I'm just going to copy or comment these out just for a second here.

And we want to prompt, we're going to say, how many viewings?

Like that.

And we want to get some input from the user.

So we've seen that put s will print a string out to the console.

To get input from the console, we can just sign a variable and we call the get s method.

And this is going to get the next line from standard input or it'll return nil when the

end of file is reached.

And then I'll just print out down here, enjoy your answer viewings, dot dot dot.

Okay.

So to run this, I'm not going to run it inside of TextMate because we've actually got to

type in a number here.

So I'm going to run it over here on the terminal, rubyflix.rb.

It says how many viewings?

Let's say we want to do three.

And it just says enjoy your, and there's a line break there, viewings.

So that's not quite right.

We want to take that line break off at the end.

And get s returns a string here and we can call the chomp method.

And chomp is just going to remove any return or enter characters hanging out at the end

of that string.

So now if we run it, how many viewings?

Three.

Enjoy your three viewings all in the same line.

Perfect.

So now we want to pass this answer, the number of viewings, over to our play method.

So let's just move this code down here.

So we're prompting.

When we call play, we want to take answer.

Now because we took this from standard input, answer is going to be a string and the play

method expects an integer.

So let's just convert it to an integer like that, calling 2i.

Now back over in the command line, if we run it, how many viewings?

We want three.

There we go.

We got three viewings of all of our movies.

It would be nice if we could enter a number, say three, it would go through all those viewings

and then it would just prompt us again for how many more viewings we wanted to do.

So to do that, down in here, we can actually add just a real primitive looping construct.

The loop in Ruby just takes a block, do end, like that.

I'm going to say how many viewings.

I'm going to put a new line here just so that we see each different prompt that comes up.

And actually I need this play inside of there as well because we want to play it a number

of times.

Okay.

So we're just going to loop around asking how many viewings and then call play.

So let's try that.

How many viewings?

Let's say we want one.

We got one viewing.

Then we're prompted at the bottom again.

How many more viewings?

Let's say three, maybe 10.

There's only one problem.

We can't get out of here.

We just have to keep entering numbers.

It's a true movie marathon.

This is a very long movie marathon.

You just keep watching, right?

Now we can get out of here by doing Control C, but that's not very good.

So rather than just continuously looping, we'd like to arrange things here so that

the user can type in like little commands and then we'll respond to those commands

using a conditional and take a different path of code depending on what they want us to

do.

So we're going to return to our old friend the case statement to do that.

So inside of here, inside of our looping construct, let's say we want to say how many viewings

and then we'll also print out that they can type in say quit to exit the program.

Now, so we want to respond to some commands and we're going to use the case.

We've got our answer here.

We're going to set up our case statement.

Its target is going to be whatever's in that answer variable.

So let's just try a really easy one here.

We've got win.

So we want to say if they enter something like quit or we'll also support maybe exit

just in case they want to try that.

Then what we'll do here is we'll take our playlist and we'll print the stats because

we're all done.

And then we're going to call break, which will break us out of this surrounding loop

because the game's over.

We do that.

We don't need print stats down here because we've already got it inside of this win statement.

Now we're responding these commands, quit or exit.

What happens if they enter an uppercase Q or an uppercase E?

Well we can solve that just by after we get the get us here and we chomp it, we actually

call downcase.

And that way every command that gets typed in, we're going to automatically downcase

it and then we're going to match against these particular words.

So if they don't enter quit or exit, then we just want the else part of this to be please

enter a number or quit.

So if they don't enter quit or exit, then there's this fallout case where we just tell

them what to do.

And then we're missing one more here.

Now we also want to branch for if they enter a number.

So we want a different win here.

And I'm going to use a Ruby regular expression to do this.

Regular expression goes between these slash characters and I'm going to say the regular

expression or the thing that they type in has to start with one or more numbers and

also end with that.

So basically just like match against any number.

Now regular expressions in Ruby is a whole course unto itself.

This is just a little regular expression.

It's just going to match the characters against a number.

So we're going to get into this win clause here if they've entered a number.

What do we want to do if they enter a number?

Well we just want to play the playlist, passing in that number and we can drop this.

So let's go through this again.

We get the answer.

If it's a number, we play that many times.

If it's quit or exit, then we're going to print the stats and break out of this loop.

Otherwise if it's neither a number or quit or exit, then we just have to tell them, hey,

you got to enter a number or quit.

So let's try that out.

Go back to the console.

I'm just going to clean that up a little bit.

How many viewings?

Let's say one, three.

Now we're all done.

Let's enter something that doesn't work.

Just enter like ABC.

It says please enter a number or quit.

We enter quit and then it prints out all the stats for the movies that got run.

All right, so far so good.

Now we need to help out our non-programming friends who want to add their own movies.

Well we could let them put the movies inside of a file.

We just use a comma separated file with the movie name in the rank and then we read it

in.

Sure, sure.

It could look like this.

Then they can put in whatever movies and rankings they want.

They don't need to write any Ruby code.

Then our application will read in that file and create the movie objects for them automatically.

So here's our movie file.

We've got our three movies in here in a comma separated format.

We want to be able to read these in.

I just created a quick file called files.rb so we can play around with files a little

bit.

So opening files in Ruby is really easy.

We use the file class.

We call the open method and then we pass in the name of the file, movies.csv in this case.

That returns a file object.

We can assign it to a variable.

And then we would do something like we would read the file here and then it's polite when

we're done with the file to actually call close on that file.

But sometimes it's difficult to remember to call close.

So there's actually a better way to open a file.

Instead of assigning a file variable like that, we can actually pass a block to the

open method.

The block will get as a block parameter the file object.

So open opens the file.

Then it hands us that file handle in the file variable here.

And then inside of here we can read our movies.

And the really cool thing about using a block here is the block will take care of closing

the file when we're done with whatever we're doing with the movies.

So what do we want to do inside of this method?

Well, we can use this file object.

And there are several iterator based methods available on file objects and other IO objects

in Ruby.

And one of those is each line.

That's an iterator that iterates through each line of the file and it gives it a block parameter

to our block.

And we can just print out that line.

And if we run this, we should see our three movies, Goonies, Ghostbusters, and Goldfinger.

But there's actually a slightly easier way to do this in Ruby.

Instead of calling open and then iterating through each line, we could actually just

call the read lines method.

Read lines is going to read all the lines of that file into an array.

We know that we can iterate through an array using each.

This is going to yield to us each line because it's just iterating through the array of

lines and we can print out the line that way.

Just like that.

Run that and we get the same thing.

Okay, so cool.

Now we can read the lines, but we still need to parse out the name from the rank.

We need to put the two things into fields or something.

Ruby's really good at this sort of thing.

So let's jump over to IRB and we'll see how to do that.

So here's what our line looks like.

We've got something like Goonies and 10.

Actually, we don't have a space in there.

It's just Goonies and 10 like that.

And we want to split this line into two things.

Well, it may come as no surprise that there's actually a method on a string, line is a string,

called split and then it takes a string, what delimiter we want to split on.

In this case, we want to split across a comma and it returns to us an array of two elements,

Goonies and 10.

So then we could just say, okay, well, the name is in position zero and the rank is in

position one like that.

Just like arrays we're already familiar with.

Yeah, exactly.

But there's actually an easier way to do this.

We can have two variables on the left-hand side, title and rank.

We can call line.split on that comma and Ruby will go ahead and assign, it'll take that

array apart and it'll assign the two parts to the variable.

So if we look at title, we have Goonies and we have rank, we have 10.

So let's put all this together.

If we come back over to our files, what we actually want to do is create movie objects

out of here.

So just up here, I'm going to require our movie file like that.

And instead of just printing out the line, when we read through all the lines, I'm going

to take the title and the rank, just like we did in IRB.

I'm going to split the line across the comma and then we can create a new movie, object,

movie.new, pass in the title, pass in the rank.

We're going to convert the rank to an integer because that's what a rank should be in a

movie.

And then we can just print out the movie like that.

Run that and we have our 2S method being called on our movie.

So we've got our three movie objects just the way we want.

So now let's take this code and actually put it over in our playlist class.

I'm just going to copy it out of here.

I'm going to go over to playlist and I'm just going to do this at the top just so we can

see it.

I'm going to define a method called load and it's going to take a file name.

I'm going to call it from file.

We're just going to paste in this code just like that.

So we're going to read all the lines of whatever file gets passed in, from file.

We're going to create a movie object just as we did before.

But instead of printing out the movie here, we're going to call our add movie method and

we're going to add that movie right into our playlist.

Now over in our flix.rb file, instead of adding the movies this way, we're calling that explicitly,

we can actually get rid of that and we'll just call playlist load and we'll give it

the name movies.csv.

Save that away and then we can jump out to the command line, get out of IRB here and

we should be able to run flix.rb.

How many viewings?

One.

And we see that we have all of our movies being played in the playlist.

They were all read from that file.

Now what if I have multiple movie files like I have movies.csv, Batman movies, csv, movies

with Tom Hanks, csv.

I see where you're going with this.

So we want to be able to pass in a file name from the command line instead of hard coding

this movies.csv thing.

Right.

Right.

We can do that.

So over in flix.rb, we don't want to hard code this name.

We want that to be our default input file name.

But we also want to be able to take a file name from the command line.

And command line arguments are stored in a global variable in Ruby called argv.

If there's one argument on there, we're actually going to call shift which will remove it from

that array of command line arguments.

And that way it won't be used later on in the program.

Then we're going to use this or constructs.

We're going to say, okay, if the argv array has anything in it, then go ahead and return

it to us and use it.

Otherwise, if shift returns nil, meaning we didn't pass in an argument, then go ahead

and use the default movies.csv.

Okay.

So let's create another file of movies here.

We'll call this our...

Let's call it superheroes.

Superhero movies.csv.

All right.

What do you want in here?

That's all.

Let's do Batman, Spider-Man, Superman.

Superman.

Superman.

Superman will get a rank of eight.

All right.

We've got that file.

Let's go back to our command line.

All right.

We can quit out of here.

So now if we run flix.rb and we don't give it any input here, well, then it's just going

to use Goonies, Ghostbusters, and Goldfinger.

That's what's in movies.csv.

But if we run it and we pass in the name of a file, let's say it's the superhero movies.csv,

well then it's going to use our superhero movies.

So now we can just pass in any valid file name and create movies and add a new playlist

in any custom way we want.

Now wasn't there one more request that you got?

There was.

We need to turn this inside out.

We want to save off the movies and their final rankings to a file, something like this.

So let's just try something here.

Suppose we have these three movies and they're all inside of an array and we want to create

a movie rankings file with them ordered from highest to lowest.

So we've seen that we can open a file.

In this case, we want to open a file.

We'll call it movie rankings.csv.

And a little bit different than we opened a file before, we want to give it a mode.

We're going to open it for writing.

We're going to write to this file.

So we give it a W. And then that takes a block.

And then we're going to get the file variable here.

And then what we want to do is we want to loop through all the movies.

We'll go ahead and sort them because we can do that.

We'll loop through all the movies using an iterator.

And then for each of those movies, we're going to use our file handle.

We can call put as on that file.

And then we're just going to print out a string.

It's going to be movie title, comma, movie.rank, just like we would expect the CSV format to

be.

So if we go ahead and run that now, nothing happens, but if we look back, we go back to

terminal here, we see we've got a movie rankings.csv file.

I'll just use the cat command and we'll print it out like that.

And we see that we've got our movies saved off in a CSV format.

So let's come back to this code.

And it's pretty good code.

Let's go ahead and take it out of here.

We'll go back to our playlist.

We're going to find a new method inside of playlist, we'll just put it right below load.

We're going to call this one save.

We're going to call it save.

And it's going to take a to file.

We could even put a default on there if we want to.

Let's say the default file that we're going to save to is movierankings.csv.

We're going to paste in the code that we just had.

We're going to change this hard coded string over to to file.

And then instead of movies, we're going to use our at movies because that's our instance

variable inside of this file.

And then over in flix.rb again at the bottom, when we're all done, we're just going to call

playlist.save to call that method.

And we'll go ahead and use the default file name there.

So let's try that out.

We'll come back to the console.

I'm going to remove movierankings.csv.

I'm going to run ruby flix.rb there.

Go ahead and run three viewings.

And then when I quit, if we have a look, if we look at movierankings.csv, we've got all

of our rankings in there.

All right.

I think we've made everybody happy in terms of our feature requests.

But I see some areas where we could use a little cleanup.

Yeah.

There are a few areas of the code that we could definitely clean up.

So let's do that.

So back over in this save method we just wrote, when we're trying to convert this movie over

to a CSV format and then sending it in to put us, it should be nice to encapsulate this

as some method.

It looks like it should be on movie because we're getting the movie's title and the movie's

rank.

So let's just take that out.

What we'd rather do is just take the movie object and call something like toCSV because

we have a toS method that converts it to a string.

How about a toCSV method that converts it to CSV format?

So we'll go over to our movie and I'll just define that.

I'll just do it up here so it's nice at the top.

Call it toCSV.

We'll just paste in that code.

It's just going to return a string.

We don't need this movie object here because we're inside of a movie instance.

We're just going to use our instance variables at title and at rank.

And that way if we ever need to convert a movie to CSV, we can just call this toCSV

method.

So back over to our playlist.

We've got that one cleaned up a little bit.

Up in the load method we've got something similar.

It's kind of the reverse situation.

We're having this line that's comma separated and then we want to create a movie object

from that and then we add it to the playlist.

So it's kind of doing a lot of stuff here.

So we'd like to be able to take this parsing code out of here and then just have a method

that will create a movie from a line.

So we kind of want something like this.

We want to add a movie.

We're not going to have a movie object, but we'd like to be able to call something like,

you know normally we call movie.new to create a new movie, but what if we had a method called

fromCSV and then it took that line, it would parse the line and then create a new movie

object for us.

So then we could take this code, cut that out of there.

Over in our movie class again, we can define that.

I'll just do it up here.

Now normally we would define this as fromCSV, but remember we don't have a movie object

to call this on and we need an object to call an instance method like this.

So instead we saw with modules where we could define methods using self.

And that gave us a module method that then we could call directly on the module.

Well using self.here we'll create a class method, which means we can call fromCSV directly

on the movie class, which is exactly what we want because we don't have an object.

So all we need to do in here, split the line.

Actually this method has to take the line in as a parameter.

We're just going to split the line and then we're going to create a new movie based on

the title and the rank.

One other little thing I want to do right here is this toI method that gets called.

If the number in that file isn't, if it's actually not a number, if it's a string or

something like that, somebody didn't put in a proper rank, then this is going to convert

whatever that is to zero.

We'd rather it raise an exception because if there's not a number in there, it's really

problematic for our program.

So instead we can use this method integer like that and pass in the rank.

And that way if the rank isn't actually an integer, we'll know it straight away because

it will get an exception.

So it's just a little nicer way to do validations on things coming in from files.

So back over to our playlist, we're calling fromCSV on the movie class, we're calling

toCSV on a movie object.

So let's go try that out.

Over here we can run Ruby, Flix.rb and then we say how many viewings?

One.

All right.

Our movies are still being read in from our input file.

We'll do quit and then if we have a look, we should have movie rankings and sure enough

it wrote them out in CSV format as well.

So now that you know the ins and outs of Ruby, you can add some IO to your game.

When you're done with the exercise, your players or the users of your game will be able to

run the game with an arbitrary number of iterations.

They'll be able to read custom player files, custom players from a file, and then they'll

be able to save the high scores off to a file.

And in the next section we'll learn about inheritance and we're not talking about all

those family heirlooms you're going to get handed down from your parents.

See you then.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.