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
Hey, it's time for the grand finale.
Now we want to package up our code as a Ruby gem to make it easy to install and download
and distribute to other people.
And the first thing we need to address is that all of our classes are defined at the
top level of our program.
So imagine that you have our gem and it has a player class, and then you install another
gem and it has a player class, we're going to have a naming collision.
Yeah, so instead of defining those classes at the top level of our program, we need to
wrap them in some sort of namespace to avoid these sort of naming collisions.
And we've already seen how we can use modules to scope the names of things.
So let's revisit that.
So remember way back when we created this snackbar module.
Inside the snackbar we had this constant called snacks.
And then to get access to the snacks constant, we had to use this scope resolution operator,
snackbar colon colon snacks.
So in a way, the module is acting as a namespace.
It avoids any collisions with other modules or classes that might have a constant called
snacks because to access snacks you have to scope it properly within the module name.
So we've seen that modules can have constants.
We've also looked at modules having module methods.
And then we also saw in the previous section how we could have methods inside of modules
that get mixed into other classes.
So now we want to look at the third case of modules, which is just a way to create namespaces
to avoid these name clashes.
So let's look at a slightly different example that I created.
It's in namespaces.rb.
We've got this module called movie system.
And it has a constant called version 1.0.
We've got a module called game system.
It has its own constant version set to 2.0.
They also each have a module method called info that prints out their name and their
version.
And then so if we want to print out the movie system version, we have to scope it to the
movie system module.
If we want to call the info method, we call it on the movie system.
In the same way, to get access to the game system's version, we've got to scope it to
the game system.
And the same with its info method.
So if we run this now, you notice that we get 1.0 for the movie system, 2.0 for the
game system.
So we've already got these neatly sort of scoped versions and different methods.
But we can also put classes inside of modules.
So let's say a movie system has a class called player, for example.
And then down in our game system, we'll also define a class called player.
Now because they're inside of a module, to instantiate objects of that type, we would
have to call movie system colon colon player.
That's the name of the class, which is also a constant.
And then we would call the new method.
In the same way, to create a game system player, we'd have to use game system colon colon player
dot new.
And if we run that, well, we don't get any output.
Let me just put us in front of there.
Run it again.
And notice that we get distinct objects.
In fact, the default printout here shows you this one is the movie system player, this
one is the game system player.
So this is good.
It means we can have classes of the same name in our gem that could be of the same name
in another gem, as long as we properly scope all of our classes.
So let's go do something similar for our movie classes.
So over in our playlist class, up at the top, there's our class definition.
We're going to wrap all of our classes in a module called Flix.
And then we'll just take this entire class, and we'll just go ahead and indent it a little
bit.
And we've got that inside of the Flix module.
So let's look at our player spec.
If we try to run our player spec now, ooh, we get this error.
It says uninitialized constant playlist.
Well, that's because playlist here is actually inside of a module called Flix.
So we can actually wrap our entire spec in a module, Flix.rb as well, down at the bottom.
I'll put an end.
So this whole describe block is in the same module as our playlist class.
And now if we run it, sure enough, all of our tests pass.
So what if we try to run our top level program?
Let's go out to a command line, and we run Ruby Flix.rb.
Oh, we get the same sort of problem, uninitialized constant playlist.
So what's that about?
Well, let's look in Flix.rb, and we're requiring all the right files.
But right here, we're referencing the playlist class.
We need to reference Flix colon colon playlist, because that's the properly scoped name of
that.
Now when we go out and run it, we get how many viewings, and we can run our game, or
run our movie app here.
Now of course, we need to put all of our classes and all of our specs in the Flix namespace
but we'll go ahead and do that and fast forward.
Okay cool.
So now we have no more class name clashes.
Right, right.
Yeah.
Okay, so the next issue we need to address is that we have all of our files in one directory.
We need to kind of organize that a little better so we have multiple directories.
Yeah, so we need to put our code in one directory.
We'd like to put our spec files in another directory.
What to name those directories?
Well, RubyGems has some conventions on how to organize our files to create a good gem.
So let's go ahead and create those directories.
Perfect.
So we have all of our classes in modules.
Now we're going to create some directories.
We're just going to create a directory over here, put all of our class files in.
The convention is to use a directory called lib, and we'll just take our class files,
movie, everything but our specs, our playlist, rankable, all this good stuff, and we'll just
drag it down into the lib directory.
We've got that.
And then our specs go in a directory called spec singular.
We can take our movie spec here, playlist, snack bar, all those specs, drag those down
into the spec directory.
So what we have left is we've got our main driver program.
Now that typically goes in a directory called bin.
It's like a command line utility for using our gem.
So I'll just drag that down into there.
It's also polite to have a license file that just has the license of your code and also
a readme file to tell people how to use your gem.
Oh, we've also got this movies.csv.
This is kind of like part of our command line interface, at least an example of a file that
has movies.
I'm going to drag that down into bin as well.
So we've got lib, spec, and bin.
Now remember all of our class files are in this module called flix.
So down inside of lib, it's very handy and easy to find files if we actually mirror that
structure here.
So I'm going to create a folder directory under lib.
I'm going to call it flix.
That's the name of the module.
And then move those files down into the flix directory.
So that way the directory structure flix and then the file matches the module flix as well.
I'm going to do the same thing with spec here.
I'm going to create a folder here called flix and move those files down into flix, just
like that.
So now let's try to run our program from the command line.
We'll use Ruby and then we'll have to go into the bin directory and run flix.rb and it fails.
It says it can't load the file playlist.
So what's going on there?
Well, if we look at flix.rb, it's down in bin, remember that we're saying require relative
playlist, which means it's expecting to find the playlist file relative to this file, which
is in this directory bin.
So we need to change this around because the playlist actually lives up one directory down
in the lib subdirectory and then the flix directory under it.
Now that's going to fix that up.
But one other thing we want to do here is this file name is relative to wherever we're
going to run this program.
And it'd be nice if we could run it from wherever, especially when we install this in the gem.
So we want to give this file name actually an absolute path.
The way we can do that is I'm going to say default movie file is equal to, and I'm going
to use the file class again and we can join some paths together here.
I want the directory of the current file.
That will be the bin directory, the directory where this flix.rb file lives.
And I want to join onto that, then the name movies.csv.
And that's going to resolve to an absolute path.
So then we can pass that in as our default movie file.
So no matter where we run flix.rb, it's going to be able to find this movies.csv file because
it's going to have an absolute path down to our current directory.
Save this away.
We should be able to go run our program and it's working as it did before.
Now it'd be nice to be able to run this, especially if we distribute this as a gem.
Instead of saying ruby bin flix.rb, it'd be nice to be able to run it kind of like a command
in the same way that we were able to run rspec as a command.
It doesn't have a.rb extension.
We don't have to type in ruby before that.
So how would we do that?
Well, we could move or just rename our flix.rb file to just flix.
So we'll just take off the rb extension.
If we look at bin, sure enough, it's now called flix.
So now we can run ruby bin flix and our program runs.
So how do we get rid of typing in ruby before that?
Well, if we go over to the flix file, at the top of this, we can put this little incantation.
It's called a shebang notation and we just say we want to run usr bin env ruby.
So that says when you run this file, use the environment to find the ruby interpreter.
Go back to the command line.
We're going to change the mode on this file so that it's executable.
This is a Unix thing.
And now we can just run bin slash flix.
So it looks like a little command.
You don't have to type in ruby, no rb extension, and it's running our movie app.
And when people install this as a gem, they'll just be able to run flix as a command, just
like typing in rspec.
Now before we get ready to distribute our gem, we should probably check that all of
our specs run.
That's a really good idea.
So let's just try it.
Rspec.
Ooh, it can't even run our specs right now.
It can't load the files or even find them.
So what's going on there?
Well, let's go look over at our specs.
Movie3dspec.rb, for example.
We've got it inside of a module, but notice that we're using require relative inside of
our specs and movie3d isn't relative to this file.
So we need to change this.
And what happens is our spec will automatically add the lib and the spec directory to Ruby's
load path.
So by doing that, we can just call require because require is going to look at Ruby's
load path, try to find a file, and we're going to require flix slash because that's going
to be relative to the lib directory.
That's on the load path.
We've got to go down and find it under flix.
So we need to change all of our specs now to use require, which I'll just do real quick.
This one's going to be require flix.movey.
Our playlist is going to require flix slash playlist.
And our snack bar, change that one around real quick.
It'll be flix, just like that.
Now, if we go back out to the command line and clean that up, we should be able to run
rspec and now all of our test paths.
You notice that we didn't have to type rspec dot because rspec will automatically look
in the spec directory for all of our specs.
Okay, so now that we have all of our files organized according to the Ruby gem convention,
we're ready to write our Ruby gem.
But the first thing we need to create is a gem spec.
Yeah, we've got the directories there, but Ruby gems needs a little bit more information
about our gem before it can actually use it.
So we'll write a gem spec file, I actually already have one prepared, and then we'll
use it to actually create the Ruby gem.
So let's look at that.
So here's our gem spec file.
It's in a file called flix dot gem spec, and it's a little, basically a little domain specific
language for specifying what your gem is and what it does.
And it's pretty straightforward and fairly self-explanatory.
We've got the name, which is always lowercase.
We're going to call our gem flix.
It has the version number, which I've set to 1.0, author, email, a really short summary
of what the gem does.
A longer summary goes in description.
And you notice because this is a Ruby file, I can actually use Ruby code.
So I'm going to say file read, and I'm actually reading the contents of the readme file that's
in our directory, which has more of a description about this gem.
So that'll be put in that field.
We've got our homepage.
Then we list all the files that are associated with this gem.
And I've used another little Ruby mechanism here.
I've used the dir class, and I'm using a wildcard match here saying, give me all the files in
bin and lib and spec.
It'll put those together.
Plus, notice I'm using this little shortcut array syntax to create an array that has the
license and the readme in it.
And then I'm concatenating that array onto the array of all the other files.
So this just creates one big array, all the files that are in our gem.
I've also listed all of our test files.
Those are down in the spec directory.
What our executable name is, the executable's name is flix because the previous thing we
called it flix.
And then really important for this gem, we're saying that we're requiring Ruby version greater
than or equal to 1.9 because we're using things like require relative, which are only supported
in Ruby 1.9.
Also, just as a little hint here, I said add development dependency R spec.
And development dependencies aren't installed by default, so they're not activated when
the gem is used, but it's nice to put in any development level dependencies.
So now that we have that, we can go build our Ruby gem.
I'm just going to save that, go over to the terminal session here.
And the way we create our gem is we say gem build, give it the name of our gem spec.
All right, it said it successfully built Ruby gems.
And if I look inside of this directory, I now have this flix dash the version name and
then dot gem.
So then we can go ahead and install it locally as a test.
And we just do gem install and give it the name of that file.
It's just a local gem file.
It's going to install it right here on my box.
And I can do a gem list.
I'm going to search for the flix gem and just give a little bit of description there or
details about that.
And sure enough, you see it says flix 100 and it has some of that information that we
had inside of the gem spec.
So now if I open a new terminal window, just to get out of this directory structure, so
there's nothing on my sleeve here, I've got the gem installed here.
I can just type flix because remember that's the name of that command we created in the
bin directory and it's part of the gem.
We listed it in the gem spec as an executable.
And if I type that, we have our movie app running.
So I want one listing, it found our movies.csv file, loaded it up, and we've got all of our
three movies being played here.
I'll just quit out of there.
And then when I'm done with the gem or if I don't want it installed on my box, I can
just say gem uninstall flix.
It has this executable.
It's also going to ask me if I want to remove that.
Sure enough, and the gem is uninstalled.
Now at this point, we can share our gem file with anyone.
We can send it to them in a file.
We can email.
We can put it on a server to download.
Yeah, let's actually put it up on a public server.
We'll put it on rubygems.org where most of all the public gems live.
Perfect.
So you'll need an account on rubygems.org, but after you have an account, you can push
the gem file to their public server.
So let's do that.
We say gem push.
We give it the name of the file.
We've got it living there, our gem file.
And it went ahead and pushed it up there.
It registered the gem as flix 1.0.0.
I can go ahead and search for it.
I'm going to search for the remote server flix, not the one that's installed locally.
In fact, we uninstalled it.
Remote gems.
It's going to go looking for flix.
There it is, flix 1.0.0.
And we can go ahead and install it from rubygems.org.
And it went ahead and installed it.
So let me just go to a different directory just outside of this directory just to show
that the gem is installed.
We can type flix again and got our movie app running.
Got all of our movies inside of there.
Or we could actually use this as a library.
Let's load up IRB.
And then we can say require flix playlist.
It's our playlist class.
And it says true.
And then we could actually create a playlist.
Let's create one.
It's inside the flix module.
Let's create one for gonzo.
Gonzo's playlist.
Like that.
Now we've got a playlist.
Let's create a movie.
It's inside the flix module as well.
Let's create a Muppets movie.
The Muppets.
It's got to have a rank of at least 10.
And now we can call playlist.addmovie movie.
And playlist will play one iteration of those.
So we can use our gem either as a command line utility or as a standalone library.
We can just load up the classes and use those.
Okay.
So this is it.
This is your first ruby gem, your last exercise, and your big moment to show off your new ruby
skills.
Now you might want to cue up some of your favorite tunes while you're working through
this exercise because in the end we expect you to do a victory dance.
And you might be wondering where you go from here.
We'll come on back and we're going to help you out with that in the next section.
See you then.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.