Ruby Fundamentals


  1. 10,000ft View of Ruby Before launching into installing Ruby tools let's take a step back and talk about what kind of language Ruby is and therefore what kinds of problems it's suitable for. What initially attracted me to Ruby was that its creator has a focus on helping developers be productive and happy. It was a refreshing attitude. As I started using the language I found that Ruby allows me to write very clean and readable code with minimal levels of syntactic and semantic noise. It also comes with a huge amount of useful functionality built into its extended library. Ruby was first released in 1995 and over the years a large ecosystem of third-party libraries and frameworks grew around, particularly in the web development arena. The focus on productivity and developer happiness is awesome, but let's also take a look at the other aspects of the language. How does Ruby compare to other languages? Ruby is thoroughly object oriented as it was inspired by small talk. There are a few primitives and many things in Ruby are expressed in terms of objects and methods. It is based on dynamic typing and duck typing. Dynamic typing means that a variable can refer to objects of different types during the course of program execution. Duck typing means that valid semantics undetermined by the objects type, instead it's enough for the object to have the methods which the operation uses. This allows you to have polymorphism without inheritance, so class hierarchies can be a lot simpler. It also gives you the opportunity to write _____ code. The flip side is that it may require more discipline from the programmers working on the code base. In addition to object oriented style of programming, Ruby is flexible enough to allow functional and procedural styles of programming as you will see in the examples during this course. Ruby has a lot of facilities for reflection. It can get a lot of information at run time, such as class methods, inheritance hierarchies, and so on. Another aspect of Ruby is that it provides rich opportunities for metaprogramming by various hook methods, as well as the ability to create classes and methods dynamically. As this course is about fundamentals I won't devote much time to metaprogramming, but I think it's important for you to know that it's something that's available to you. The widely used implementations of Ruby are byte code interpreted. This can put some limitations on performance. The official implementation, which I'm going to use in this course, is called MRI, which stands for Matz's Ruby Interpreter. Another popular implementation is JRuby, which is built on top of the Java Virtual Machine. I should mention that on the Mac another Ruby implementation called MacRuby can perform both just-in-time and ahead-of-time compilation of Ruby code.

  2. Installing Ruby Let's take a look at installing Ruby. On Windows the easiest way to install Ruby is to use the prepackaged installer. Open rubyinstaller.org/downloads in your browser. Enter an installer for Ruby 2.0 or later. The installer comes in both 32-bit and 64-bit flavors, I'm going to download the 64-bit version. Once the installer downloads, run it and follow the steps in the wizard. On the installation destination page check the box to Add Ruby executables to your path and then click Install. Now that the installation is complete let's check that Ruby's working properly. I'm going to open a command prompt and type ruby --v which will output the version of the Ruby that's currently installed. So it outputs the version and I can see that 2.0 is installed and available. You can run Ruby programs by passing the name of a file to Ruby, so I can create a very small test file. (typing) And then I can run it by passing its name to Ruby. So it outputs Hello. Know that files with Ruby code typically have a .rb extension. If you use Linux the easiest way to install Ruby is to use RVM, a Ruby Version Manager. Some versions of Linux come with Ruby packages, but they can often be out-of-date, whereas RVM gets updated much quicker. Another benefit of using RVM is that it allows you to switch between multiple versions of Ruby easily if you have the need to write applications targeting different versions of the interpreter. Open rvm.io in your browser and on the home page you will see a command to install RVM along with the latest version of Ruby. (typing) Copy this command and paste it into the shell. When you run it, it will take a while, but after it's done you should have a shiny new Ruby installed. Again you can check that it works by running ruby --v. Mac OS X comes with a preinstalled version of Ruby, but it's also likely to be out-of-date. Similarly to Linux, you can use RVM to install the latest version of Ruby if you're on a Mac.

  3. Interactive Shell Demo The easiest way to start playing with Ruby is to use the interactive shell that comes with it. It's called IRB because I stands for Interactive and Ruby code file names normally have the .rb extension. This kind of tool is also sometimes called REPL, which stands for read-eval-print loop. It was pioneered by Lisp and it's a great tool for quick experiments and exploration. You can start it by running the IRB command in the terminal. (typing) If you run it on Windows you might get a DL is deprecated, please use Fiddle message like I did. It's just a deprecation message which is going to be fixed in the future versions of Ruby and our _____ still works fine so nothing to worry about. Now that we have this interactive environment let's dive in and look at some examples of what you can do with Ruby. Variables don't have to be declared, you just assign a value to a new variable when you need it. (typing) So now I have a variable called lander_count, which is equal to 10. _____ that irb shows the result of evaluating the expression. As Ruby has dynamic typing you can also assign values of different types to one variable. (typing) By the way you can use the up arrow to go through the history of expressions that you typed, which is a great time saver. In going back to our variable, now we can check the type of land account by using its method called class. (typing) Irb reports that its class is String. The interesting thing is that the class method doesn't just return the name of the class it returns the class itself. If you recall most things in Ruby are objects, in fact even classes themselves are objects so I can examine their interfaces too. Objects have a method called public_methods which returns an array of public methods an object has, let's try it out. (typing) This method returns an array of method names. I've also sorted the array by taking on a call to sort to make it easier to read. If I look through the method list I can spot the superclass method in it. This method allows me to traverse the inheritance hierarchy. I can type String.superclass to find out that string inherits from object. If I add one more superclass I can see that object is derived from BasicObject, which is at the root of class hierarchy in Ruby. Remember that I said that even numbers in Ruby are objects, it means that I can do things like this. So the class of this object is Fixnum or I can do this. This kind of extensive object orientation provides consistency which allows you to write cleaner code and makes your job as a programmer easier. IRB allows you to do a lot more than defining variables and call in methods, you can also define new methods or even classes. For example, I'm going to define the method called double. (typing) For convenience I've written the whole method on one line. It takes one argument, multiplies it by 2, and returns the result, let's try it out. The method returns 20 as expected. Now let's try something else. Something interesting happens here, the method returns the string, which is the argument repeated twice. Because of Duck type and the custom operating implementation in this string class, this method also works on strings. I can even use it with an array. (typing) The result is similar to what happens with strings, the result is an array repeated twice. A handy thing to know about IRB is that a special variable referred to with underscores stores the result of the last evaluated expression. So you can get access to that result even if you didn't store it in the variable. I can type double_, to double the previously returned array. Finally when you're done type exit to get out of IRB. I encourage you to do some more exploration in IRB on your own. To recap IRBs great for experimentation and exploration. You start it from the command line using the irb command. It allows arbitrary Ruby code, you can use the up arrow to go through the history of the expressions that you typed, and use the underscore variable to access the previous result, which saves you some typing.

  4. IDE Options and RubyMine Demo When you start developing complex software in Ruby you might want the assistance of an IDE to manage, debug, and test the code. I use and recommend RubyMine. It's cross platform and works on Windows, Linux, and Mac OS. It's free for open-source projects, but costs some money if you're developing commercial software. In my opinion, it's the most advanced Ruby IDE. It provides code completion and navigation, it has an integrated debugger, it can run your test suite, and even has convenient built-in source control clients. It also has extensive support for the Ruby on Rails framework if that's your reason for learning Ruby. You can download it at jetbraines.com/ruby. Another option is Aptana Studio, it's also cross platform and you can download it as a standalone application or as an eclipse plug-in, it's available free of charge. Of course you can also development without an IDE using your favorite text editor. Emacs and VIM have Ruby plug-ins and there are other editors such as SciTE or Notepad++ which have at least some support for Ruby. I'm going to use RubyMine throughout this course, so first let me show you how to create a Ruby project in it. When you open RubyMine it'll show a quick start window. Click on Create new project. Set the type to Empty project, enter a name for it, RubyMine will create the corresponding directory, but know that you can change where the source files are placed by changing the path and the location field. Press OK and RubyMine will create the project. After that I just need to add a file (typing) and I can start writing code. I'll make the program say hello to begin with. Then I can Run it and it outputs Hello! in the console window at the bottom. I'd like to dedicate the rest of the module to a kind of a bootstrap process for your learning of Ruby. I'll go over the basics like name and variables, code formatting, comments, defining methods, and so on. This will give you a foundation and let you write simple programs. With that you should be ready to dive into the details of various aspects of the language in the subsequent modules.

  5. Variables, nil, Methods and Scope Let's start with variables. I've already used variables when I showed you IRB. In Ruby defining the variable is done with a minimum of fuss, when you need a new variable you just give it a name and assign a value to it. You don't need to declare it beforehand and you don't need to specify its type. Variable names start with a lowercase letter and the idiomatic style is to use underscores in variable names to make them more readable as opposed CamelCase. What if you want to define a variable but don't have a value for it yet? In that case you can assign nil to it. Nil isn't the primitive, it's a special object that signifies null value. If I type nil.class irb tells me that its class is NilClass. I can check if a variable is nil by using its nil method. Result.nil returns true because result is actually nil. The question mark in this statement isn't special syntax it's simply part of the method name. In Ruby method names can end with a question mark or an exclamation mark. The question mark is normally used for methods which perform a true/false test. The exclamation mark is used in method names which do something slightly unexpected or dangerous. An example of that would be modifying the object in place instead of returning the modified copy. We can see this in the string class. (typing) Here I have a string with some whitespace in it. The string class has a convenient method called strip which removes the leading and trailing whitespace from a string, let's try it out. You can see that it returns a string without whitespace, however, the method returned a new string and A's still unchanged. If you want to modify A instead of creating a new string, you can call the version of strip with an exclamation mark. In this case the string object A refers to has been modified in place. Another situation where an exclamation mark could be used is if you have a method to terminate some operation abruptly without firing the normal callbacks. Normally you would only define such methods when they also have a safe count, but without the exclamation mark. You've also seen how to define the method. I defined the method on a single line in IRB like this, this isn't how you would write regular code. Semicolons are used to _____ statements on a single line, but good Ruby style is to use them very sparingly outside of IRB. Normally methods are defined on multiple lines like this. The method definition starts with the keyword def followed by the method name and followed by an optional parameter list in brackets. The definition ends with the keyword end. A method can return a value of any type, in fact it can even return values of different types depending on the circumstances. Methods return the result of evaluating the last expression so there's no need for an explicit return statement, unless you specifically want to use it for flow control. Typically Ruby code is indented with two spaces. Whitespace is not significant unless it's inside a string. When calling the method, for example like this, the brackets around the arguments are actually optional, but they are normally used when you have an argument list and omitted if you don't. There are some exceptions though and I'll note them throughout the course. Some methods are used more like keywords in Ruby, with those methods is common to omit the brackets. One example of this is the boots method, which I've used before. One more thing you need to know about methods in Ruby is that they provide scope for variables. In this example lander_count is a local variable so its visibility is limited to the scope it was created in. As it's defined at the start of the file, it's going to be visible throughout the program. If I define a variable within a method instead, then the variable is only going to be visible inside that method, but what happens if I name my variable in an inner scope, the same as a variable in the outer scope? In this example lander_count is first defined at the start of the program and then I've redefined it in the report method. What happens here is that the second definition in inner scope shadows the variable in the outer scope. I'm also calling the report method after defining it, note that there are no brackets because it doesn't take any arguments. And I also output the lander_count value at the end. When I run this program it first outputs 5 and then 10. This is because the lander_count in the report method is a new variable which exists within the scope of the method. It doesn't affect the lander_count from the outer scope, so when I print the variable after the report method, I see the value from the original definition. In addition to local variables, you can also create a global variable by prefixing its name with a dollar sign. The log_level variable is visible everywhere throughout the program. Hopefully you won't have much need to create global variables as global state is generally a bad idea and can cause subtle bugs and a lot of headaches.

  6. Flow Control, Operators, Comments So far you've seen how to create variables and methods, the next thing you're going to need is some control structures. Ruby has some familiar looking control structures such as the if-else statement. As you can see in this if statement it also has the usual operators such as greater than. However, an interesting twist is that Ruby treats statements as expressions as much as possible. The if is actually an expression which evaluates to the result of the last expression in the selected branch. So instead of outputting a string in each branch, you can do something like this. (typing) Now the if returns one of the strings depending on the value of lander_count. The result is a sign to message and then the message is printed afterwards. This property of Ruby means that you can change the assignments as well. This is because the assignment expression yields the value that was assigned. Let's have a look at some of the operators Ruby provides. This isn't an exhaustive list, but it should be enough for the purposes of our bootstrap process. I'll introduce a few more operators later on in the course. Greater than has its friends less than, greater or equal, and less or equal. You can also check whether objects are equal or not. There are other usual mathematical operators to add, subtract, multiply, divide numbers, and take the modular. There is also an exponentiation operator denoted with a double star. Ruby has the familiar logical operators representing not and as well as or, but it also has an alternative syntax where these operators are written as words. The difference with the second group is precedence. Here instead of the or operator having higher precedence, both and or have the same precedence. The second group is normally used for flow control outside of control structures such as if-else. The next group is bitwise integer operators. We have the usual suspects here, bitwise and/or exclusive or complement as well as operators for shifting left and right by a specified number of bits. Ruby also provided a bunch of convenient shorthand operators which combine assignment with another operation. So for example, a+=10 is the same as a=a+10. Finally code always requires a sprinkling of comments. In Ruby anything following the pound sign is a comment. Comments continue until the end of the line.

  7. Some Useful Methods The last thing I'd like to demonstrate in this module is a few useful methods. The first thing you might like your programs to do is to take some input and produce some output. Let's look at a small example which does that. So here I use print which outputs a string. It's convenient when you need a prompt for example. Then gets, waits for your keyboard input and returns it and the puts call outputs a string combined with your input. Note that the puts method adds a new line to the string. Let's try this program out. I'll input my name and the program outputs a greeting which includes my name. Let's look at one more example. Ruby makes it very easy to execute a command in another process and collect its result. I can use backticks to specify a command to execute. In this program I'm asking for the time from the system. It'll be launched in a separate process and the Ruby process will block until it's complete. The output of the command is then returned to Ruby so I can store it in a variable and output it. Instead of backticks, you can also use %x. (typing) The system method is similar, however instead of the command output it returns true if the command finished with 0 status and false for non 0 status. It returns nil if the command failed. The output of the command is part of standard output which is why we see the time printed twice when I run this program.

  8. Recap Let's quickly recap what you've learned. Variables are named using snake_case not CamelCase. Defining a variable is a simple assignment. Global variable names start with a dollar sign, but I hope you won't need them. A variable in inner scope will shadow a variable of the same name previously defined in outer scope. You can assign a variable the value of nil. Nil is a special object which signifies null value. Methods are defined using the def keyword. Methods return the result of the last expression. You don't need to use an explicit return statement. You should indent your code with two spaces, it's not a hard requirement as Ruby doesn't care about whitespace, but it's very common practice. You've seen that Ruby has familiar looking operators and control structures, however, as Ruby treats most things as expressions, you get extra convenience. Comments start with a pound sign and go on until the end of the line. Input and output can be done using the gets, puts, and print methods. And finally you can easily call out to the system using either backticks or the system method.

  9. Summary This is the end of module 1. In this module you've learned about the principles underlying the Ruby language and its implementation. You've seen a demonstration of its interactive shell, IRB, and one of the IDEs, RubyMine. You've also learned the basics of the Ruby language. You now know how to define variables and methods and how to format and comment your code. You've seen some examples of Ruby control structures and operators. And you've found out about some useful methods.

  10. Classes and Objects Overview Hi this is Alex Korban. In this module you will learn about Classes and Objects in Ruby. You will find out how to create your own classes and how to instantiate objects from those classes. You will learn how to add instance variables and methods to your classes. You will find out how to control the visibility of these variables and methods. I'll show you how to initialize your objects. You will see how to create class variables and methods. You'll also get the hang of leveraging inheritance to re-use functionality. Finally I'll talk about self, which refers to the current context. I'll talk about what it means to have executable class bodies in Ruby and object equality.

  11. Creating Classes and Objects To begin with let's look at how you can create classes and objects. Class definitions start with the class keyword and end with the end keyword. Generally the end keyword is used to finish all blocks of code. The way you capitalize identifiers in Ruby is significant. While variable names start with a lowercase letter, class names start with an uppercase letter. Multiple words and class names are delineated using CamelCase and acronyms are normally written in uppercase letters. To instantiate an object from a class you use the new method of the class. Remember that in Ruby you typically omit brackets when defining or calling methods without arguments. You can think of the new method as a factory which converts the blueprint encoded in the class into a specific object. Let's take a moment to talk about variables versus objects, it's important to understand the difference. Although most things in Ruby are objects, variable aren't, instead variables are just labels for objects. Suppose I assign a string to a variable. Now I have a variable called A which refers to an instance of the string class. What happens when I create another variable like this. There is still only one object, but now I have two different labels called B and A, which refer to it. Now let's check that it's indeed the case. If I convert A to uppercase like this, this modifies the object in place. So if I look at A the string is in uppercase. This is because I used the version of uppercase with an exclamation mark. Now let's take a look at B. Well look at that, B has also changed, which means that there is one object both variables referred to. We can also verify that both B and A refer to the same object in another way, by checking the unique identifier of the object. For that I use the method called object_id, so that's the id for A. And this is the id for B and we can see that it's the same. When you pass arguments to a method the behavior is similar, the objects are passed by reference without creating copies, but what if you really need to create a copy of an object? Then you can use the clone method from the object class. This will create a new object. So when I modify it (typing) I can see that A and B now refer to two different objects. You should be aware that clone doesn't perform deep copy. If I had references to other objects within it, then B would refer to the same objects. In practice, however, this isn't often a problem. So remember that neither assignment nor passing parameters to methods creates new objects. If you want to create a copy of an object you need to use its clone method.

  12. Instance Variables and Methods The spaceship class, I showed you before, couldn't do anything useful because it's empty. Let's give it a little bit of functionality. I've added the method called launch which takes this destination as its argument. Let's also make it store the argument in an instance variable for future use. Instance variables in Ruby are denoted with @. They're called instance variables because each instance of the spaceship class is going to have its own copy of destination. Note that the destination instance variable is only created if I call the launch method. Before that it doesn't exist. So let's take this method for a spin now. I've got the same class in a project in RubyMine. You can also see here that I can freely mix class definitions with other code in the same file. Ruby is low on ceremony so it doesn't dictate any particular code organization. Once I've set the destination via the launch method I can take a look at the state of my ship object with the help of the inspect method. If I run this program, I can see in the output pane at the bottom that destination has indeed been set. Instead of inspect I can also use the method called simply P to print out information about the object. If I rerun this program I see the same output as with inspect. What if I want to access the value of destination later on? Let's try it. When I run this I get an error telling me that the destination is an undefined method. This is because all instance variables in Ruby are not visible outside of the class. Instance methods, on the other hand, are public by default. In order to exit destination I have to define a method which returns it. When I run this program again it outputs Earth which is what I wanted. In this demo you've seen that you can use the objects inspect method or the P method to take a look inside the object. Instance variables of an object are private and can only be accessed via methods. Methods are public by default.

  13. Accessors and Virtual Attributes A class can have many different instance variables and defining methods to set and get each one of them would be quite tedious. For this reason Ruby provides a convenient alternative. You can use attr_accessor to provide read and write accessors for an instance variable. Here I've added accessors for the destination instance variable. The colon before the word destination indicates that it's a symbol. We'll talk about symbols in the one of the next modules. For now just remember that this is how you specify the name to access. With this in place I can now set and get the destination. Note that invoking a setter created via attr_accessor looks like assigning a value to an attribute. Sometimes you might want to provide read only accessors to a variable and in other situations you might only want to allow to set the variable. You can do that as well. Here I provide read and write access to the name variable via separate declarations. Attr_accessor actually combines attr_reader and attr_writer together, but you can use them separately. The nice thing about accessors is that the syntax for using them is very clean. You can also define multiple accessors at once by providing a coma separated list of names. One last thing I'd like to say about accessors is that there is a bit of a gotcha when you use accessors inside a class. In the cancel_launch method the first line isn't going to call the accessor method, instead it's just going to create a local variable. So to make it clear to Ruby that you want to call the accessor you need to qualify it with self. as I've done on the second line. If we dig a little deeper it turns out that attr_accessor simply adds a pair of methods to the class behind the scenes. The first class definition here is equivalent to the second. If you look at the second destination method you'll see that it's got an equals sign at the end. Once again the equals sign in the second method is just a part of its name, just like a question mark or an exclamation mark. It simply signifies that it's a setter. What if instead of using these methods to manipulate the destination variable, I do something else instead? For example, I can change this class definition so it passes the destination value to the autopilot instead of storing it. Now destination has become a so called virtual attribute. The interface of the class hasn't changed, I can still assign a string to destination and get a string back. However, under the hood there is no instance variable called destination anymore. This is another case where Ruby provides very useful consistency. I can start out with regular attributes in my class, but as I develop it, it's very easy for me to replace simple attribute access with more complex code and it doesn't affect the interface of my class.

  14. Initialization and Cleanup Most objects need to have some initial state. In order to initialize objects you need to add a method called initialize to your class. You can then provide arguments when you call the new method and it will invoked initialize with those arguments. Let's check that this actually works. When I run this program I can see in the output pane that my ship object now has a bunch of instance variables. So initialize has indeed been called. So what about destroying objects? In Ruby you don't need to do it explicitly as it has a garbage collector. Ruby has a variation of a mark and sweep garbage collector which runs periodically and cleans up the objects which are no longer referenced by your program.

  15. Inheritance Like most other object oriented languages, Ruby provides the ability for classes to inherit functionality from other classes. A class can only inherit from a single class. Multiple inheritance is impossible, but as we'll see in a later module, Ruby provides a great alternative through the concept of modules. If not specified otherwise, classes in Ruby inherit from the object class, which provides methods like clone, public underscore methods, and so on. Object in turn inherits from basic object which is an explicit blank class. In some situations you might find it useful for your class to inherit from basic object instead of object, for example if you want to avoid name clashes with methods from the object class. When you call a method Ruby checks whether it exists in your objects class. If it doesn't find it, it starts traversing the hierarchy of the classes ancestors looking for a method with that name. If it finds it in one of the superclasses it calls it and all is good, if not you get an error. For example, if I call clone on my spaceship instance Ruby has to keep looking for it until it gets to the object class. Here is an example of inheritance. Continuing with the spaceship theme let's suppose my spaceship can launch probes to explore things. I'm going to create a class called probe to represent probes. This class inherits from objects inside unspecifyied ancestor. Now suppose I would like to have two specialized probes, one for taking mineral samples from the soil and another to sample the atmosphere. Both of them share most of the functionality with the regular probe, they can be deployed and so on. However the way they take samples is specific to these probes. This is a great opportunity to use inheritance. Inheritance is specified by adding a left angled bracket and a superclass name after the class name. In my example MineralProbe inherits all of the methods from the probe class. If you have an initialized method in the base class it's also inherited along with the other methods. The next thing I need to do is override the methods which are going to behave differently from the superclass, like take_sample. All I need to do is define a method with the same name in my subclass. What if you need to call a method from your base class in your subclass? You can use the super keyword for that. Let's look at an example. Suppose that for my MineralProbe I need to perform some extra work before it's deployed, but after that the deployment process is exactly the same as for a regular probe? I can override the deploy method, add my extra bit of code at the start, I just output a string here, and then I call the probes deploy method using the super keyword. Super behaves like a function call so it's going to return whatever the superclass method returns. Note that I can actually change the number of parameters a method takes when I override it. The only important thing is that the method name matches. Let's try to run this program. So Ruby complains about their own number of arguments. What happens here is that because I used super without any kind of parameter list, it passed MineralProbes deploy method arguments through to probes deploy method. Please keep in mind that calling super with an empty argument list is different. See if I add an empty argument list and try to run this program again, I get a different error message. This time Ruby is complaining that there was zero arguments, not one argument. Any argument list given to super, even an empty one, overrides its default behavior. What I really need to do to make this work is pass through the deploy time and provide a value for return time, which is required by the Probe class. I'm going to set return time to be two hours in the future. (typing) When I run this again it works as expected. One more thing I'd like you to know is that compared to other languages, such as Java or C++, the role of inheritance and Ruby is limited. Its main purpose is to provide a mechanism to reuse functionality between classes, not to enforce interfaces. Suppose my spaceship can launch both lenders and probes, when they return they can dock with the ship under the ships control and then they are transported to the storage facility. However, the internal details of the docking mechanism are quite different for lenders and probes. To solve this problem in other languages perhaps you would make both classes implemented dockable interface so the spaceship only needs to deal with one type. However, in Ruby it's completely unnecessary thanks to duck typing. All you need to do is implement the dock method in both the lender and the probe classes and the spaceship called will work with either without any extra code. So for example I could have a capture method in the spaceship class which calls dock on its unit argument and then I can call a capture method with either a probe or a lender argument. And it will work fine as long as those classes implement the dock method. This is one of the advantages of the dynamically typed languages and duck typing in particular. The class hierarchy can be greatly simplified when you don't need to write classes which don't do anything other than specify an interface.

  16. Class Methods and Variables The next thing I'd like to show you is class methods and class variables. A class method is called on a class instead of an object. An example of a class method you've already seen is new, which is used to instantiate objects. Sometimes you have functionality which is independent of object state and this is where class methods are useful. For example, I might want to have a method to return the number of thrusters in my spaceship class. Every spaceship is going to have the same number of thrusters so this is a good candidate for a class method. Now you could make this method a regular instance method as well, but a class method makes it clearer that this bit of functionality is not reliant on object state. To define a class method you need to prefix its name with self.. The self keyword is actually more than just a syntactic signpost for class methods and I'll talk about its meaning a bit later in the module. You call the class method on the class rather than an object. If you try to call it on an object you will get an error. While class methods don't use object state, they might nevertheless have some state that needs to be preserved between calls. To keep track of it you can define class variables. A class variable is denoted with a double @, there is only one copy of a class variable per class and it's shared between all objects of that class. You define it in the body of the class. The class variable isn't visible outside the class, so you have to provide accessor methods for it if you need to access it from the outside. It turns out that in practice class variables aren't actually used very often and that's because of a quirk in their behavior. Suppose you have different types of spaceships and they can have a different number of thrusters, which you'll want to specify using the thrust account class variable. Let's try this out and see what happens. In this example I have two subclasses of spaceship. SpritelySpaceship has four thrusters so it can go really fast. EconolineSpaceship has only one thruster so it cruses slowly but saves on fuel. Now let's check the value of thrust account with SpritelySpaceship. Opps this program actually outputs 1 instead of 4. What happened here? Well, it turns out that class variables are actually shared between all of the subclasses. Spaceships, SpritelySpaceship, and EconolineSpaceship all have just one copy of thrust account between them. This can lead to unexpected results as we have seen here. Unless this is the behavior you actually want it's probably better to avoid class variables. Fortunately Ruby does have a different trick up its sleeve to allow you to store class level data. In addition to instance variables and class variables, Ruby has another kind of variables, class instance variables. Check out this bit of code. I'm certain what looks like an instance variable right in the body of the class here and I'm also using this variable in a class method instead of an instance method. Instance variables, which are set in the class body or in the class method, become variables on the class rather than an object. Let's revisit our example of using a class variable and see how this kind of variable behaves instead. This example is just like the example you've seen before for class variables except now I'm using a class instance variable to store thrust account. When I run this program it outputs the correct value for each class. What happens with class instance variables is that the parent class and each of the subclasses get its own copy of the variable, but only one per class.

  17. Method Visibility So far all the methods I've added to classes have been public because that's the default. However, Ruby does allow you to control the visibility of methods, although the rules for it aren't quite the same as in other languages. Other than leaving all methods public, you have two other options. You can make a method private or you can make it protected. You tell Ruby that a method is private by adding a private declaration after you define the method. For example I can make the batten_hatches method private like this. The other option is to use the private declaration without a method name. So in this example I want to make both batten_hatches and light_seatbelt_sign private. So I can put a private declaration before these methods and all the methods fall in the declaration will be private, either until the end of the class or until there is another visibility declaration. This is probably the most used variation of the syntax. You can mix and match visibility declarations throughout the class. Finally you can supply multiple method names to the private declaration. This is similar to how attr_accessor works. Now let's try to run some code that uses private. I've got a Spaceship class with a private batten_hatches method. Let's try to call it from outside the class. When I run this program I get an error as expected. You should be aware that in Ruby the visibility isn't enforced very strongly. If instead of calling batten_hatches directly I use the send method from the object class to invoke it Ruby will happily comply. Now on this program there is no error anymore. This is in line with Ruby's philosophy of leaving the programmer in charge. The other important thing to know about private methods is that they can be called from subclasses. In this example, I have SpritelySpaceship which is a subclass of Spaceship. Since it needs to go fast it comes with pre batten_hatches. Batten_hatches is still a private method in the Spaceship class, however when I run this program I can see that it's called from SpritelySpaceships initialize method. That might be a bit surprising if you've been programming in another language, but there's a simple rule to remember how private works in Ruby. The rule is that a private method can be called with an explicit object receiver. This makes it clear that you can't write ship.battonhatches, it also explains why you can call a private based class method from a subclass. The private method is inherited by the subclass along with all the other methods. As you are calling it from the context of the subclass you don't need to provide an explicit receiver and that's why it works. A word of caution, there is a separate mechanism for making class methods private. If you tried to use the regular private declaration you won't get an error, but your class method will remain public. The right way to do it is to use private_class_method, you can pass it one name or a coma separated list of names but you can't use it without arguments as it doesn't work on a group of class methods. Let's examine the behavior of protected methods next. It might also be a bit of a surprise. The protected method can be called on another object by an object of the same class or an object with the same ancestor if the method was defined in that ancestor. In this example I want to be able to compare ships call signs. However I don't want to make getting the call sign part of the public interface. To achieve that I've set up a protected attribute reader called call_sign. The call_sign is set in the initialized method of this Spaceship class. I also have a method called call_sign_matches? which takes an object as an argument and checks if it's call sign matches the call sign of my spaceship. To do that it has to access the protected attribute reader call sign. I also have on a subclass, called SpritelySpaceship, which is a specialization of spaceship. Next I create two objects, one is a spaceship and another one is a SpritelySpaceship. When I run this program I don't get an error, instead it outputs false. However, if I tried to invoke call_sign directly I do get an error because it's a protected attribute. To summarize, methods are public by default. Private means can be called with an explicit receiver, which does allow subclasses to use private methods. Private_class_method is used to make class methods private. Protected means allow other objects of the same class to use the method. Because of this definition protected class methods don't make sense, so they don't exist in Ruby. On a final note, private and protected methods aren't used all that much in Ruby, in keeping with the philosophy of leaving the programer in charge, lots of methods are left public.

  18. Executable Class Bodies and self By now you've seen most of the features of Ruby classes, there is one more thing I'd like to show you and this one is perhaps the most interesting. It turns out that the class bodies in Ruby are expressions just like most other things, which means they are executed like other code. The consequence of this is that you can put pretty much any code into the class definition. In this example I have a class called Spaceship which contains a local variable definition, it has a boot statement, and I even have a method call in it. When I run this program I can see that the code inside the class declaration is executed. Since the class declaration is an expression I can even assign its result to a variable. The last line of output confirms that I've also managed to define the Spaceship class in the process. In a way you can think of classes as a way of providing a context for execution of code. A method defined inside a class context is assigned to that class. What about the attr family of declarations and method visibility declarations such as public and protected? Well, they are just methods which can be called with or without arguments. The example I've shown you should give you a hint as to how that's possible. These methods are normally called without brackets, which makes them look more like keywords. You've already seen the keyword self a few times, let's find out exactly what this keyword means. Now that you know that classes provide a context for execution, it's easy to explain what self is. Self simply refers to the current execution context, whatever that happens to be. You can use self at any point in a Ruby program. Inside a class definition self refers to the class. This is why you need to prefix methods with self. to turn them into class methods instead of instance methods. It's also why you end up with a class instance variable when you assign a value to an instance variable in the class body. An instance variable is always set on the self and inside the class body self is the class itself. The value of self keeps changing as the program executes. When you call a method on an object that object becomes self inside the method. So when I call ship.cancel_launch inside the cancel launch method, self refers to my ship object. Finally any method which you call without an explicit object reference is called on self. For this reason when I call seatbelt_sign, inside cancel_launch, it's also called on my ship object.

  19. Open Classes and Monkey Patching Now that you know that classes are an execution context and that they can contain regular executable code, hopefully you'll find it easy to understand the concept of open classes in Ruby. You can see class Spaceship twice in this bit of code. That's perfectly legal code in Ruby. So what's up with the second class declaration? I'm not redefining the class, but rather I'm reopening it to add another method. Afterwards all the objects of this class are able to use the new method, even the objects which were created beforehand. However, if I tried to call ship.launch before the second class declaration I would have gotten an error. This leads us to monkey patching which exploits the concept of open classes. Monkey patching is a term used for _____ or modifying functionality particularly third-party functionality at runtime. As you have seen you can reopen a class and add a method to it, it turns out that you can also override an existing method. When Ruby encounters another definition of a method with a name that already exists, it simply overrides the previous definition. So in this example I've reopened the class Spaceship and I over road the method called batten_hatches. When our underscored I get the output from the second method definition. Keep in mind that if your original method was private or protected, the _____ definition will not preserve visibility restrictions. If I make the first definition of batten_hatches private and rerun this program I can see that it still works. That's because the second definition is public. So I have to explicitly make it private and then when I run this program I get an error as I should. You can even use monkey patching to modify classes in distended library. Here I've added a new method to class string. My new method space_out adds a space between each character so it doesn't look so cramped when printed. I've also redefined the size method so that instead of returning the number of characters, it returns a rather useless string. When I run this program you can see that I've got new functionality in the string class. Monkey patching is sometimes used to fix bugs in third-party libraries. While it is useful you should use it judiciously because it changes the behavior of the code other users make expect, or it can introduce new and potentially surprising methods. It can also make your code more brittle because, for example, when you upgrade a library the assumptions you made when patching it may no longer be valid and your code will no longer work.

  20. Equality The final thing I'd like to discuss in relation to classes and objects is equality. At the start of the module you've seen that if you assign one variable to another, both will refer to the same object. Sometimes you'll need to find out if two variables point to the same object. You can use the equal method to test if two variables in fact point to the same object. I made A and B equal to 1. If I use the equal method it returns true. If I make B equal 2 instead then equal will return false, as these variables now refer to different objects. That's fine but it's not the end of the story. What if I have two instances of an object representing the same thing? For example, what if I have several instances of Spaceship created throughout my program and sometimes I need to check if two instances really represent the same Spaceship. Obviously if I tried to use the equal method it's not going to work. Equal predictably returns false. Spaceship should really have unique names, so if I check the name in both objects and it matches then it means they both represent the same Spaceship. So I could write ship1.name == ship2.name and that will give me true, but that's a bit un-_____. What else can I do? One option is to override the equal method to do what I want, but then I won't really have the ability to check if two variables refer to the same object. Another option is to provide a method in the Spaceship class to perform this comparison for me, but let's look at that name comparison again. When I create two string objects in Ruby (typing) and then write a == b I get true, but if I write a.equal?(b) I get false. So Rubys showing the ability to compare two different objects here. Well it turns out that I can provide a custom implementation of the double equals operator in my class which gives me a nice bit of syntactic sugar. The default implementation does the same thing as the equal method, which is why I need to override it. So here my operator is simply comparing the names of the two Spaceships. So now instead of writing ship1.name == ship2.name I can simply write ship1 == ship2 and when I run this I get true. I'll come back to operate overload and then discuss it in more detail later, but for now when I try this comparison it works and lets me make testing for equality clear and concise.

  21. Summary This is the evnd of module 2. In this module you've become familiar with objects and classes in Ruby. You've learned how to add class and instance variables and methods to your classes. You have found out how to use inheritance to specialize classes and how to limit method visibility. You've also learned about self, the concept of open classes, monkey patching, and object equality.

  22. Flow Control Overview Hi this is Alex Korban in this module you will learn about Flow Control in Ruby. I will start with branching via if-else and the case statement. I will then show you the various looping constructs and talk a little bit about blocks. I will tell you about exception handling. Finally you will see what throw and catch do in Ruby, which is probably not quite what you expect.

  23. Branching As you've seen before Ruby has a pretty _____ if-else statement, however, it also works as an expression, so you can assign its result to a variable. If you do that it may be convenient to keep it on one line. Note the optional then keyword which is used to separate the condition from the next statement. You would normally use it when writing an if statement on one line, but not for a multiline if statement. Ruby also has a so called modify version of the if statement, this version can't have an else clause and works best for a short statement followed by a short condition. If you want to test multiple conditions you can use multiple elsif clauses, which can be supplemented by a catchall else clause. Note that elsif is one word. In Ruby there are only two things which evaluate to false in conditions. These things are nil and a literal false. Everything else, such as number 0, empty string, empty array, and so on evaluates to true. If has a count part called unless in Ruby. Unless has the opposite effect so if not condition is equivalent to unless condition. Using unless instead of negated conditions can make your code a bit more readable. Unless can actually have an else clause, but my advice is not to use it because it gets rather confusing. Like if, unless has a modifier version which can be tagged onto a statement. As a more succinct alternative to if-else Ruby has the ternary operator. If the first operand evaluates to true, then the second operand is evaluated by Ruby. Otherwise it evaluates the third operand. The result is returned same as with the regular if. This works well for single line conditional statements. I'd advise against nesting ternary operators as it makes the code hard to understand.

  24. Conditional Initialization You've already seen the shortcut assignment operators which combine assignment with another operation, such as += or *=. Ruby also has two other shortcut assignment operators or= and &=. The &&= operator isn't used a whole lot, but the ||= operators is very very common because it can be used for conditional initialization of variables. This line of code will call Spaceship.new and assign it to the ship variable, but only if the ship variable evaluates to false or doesn't exist. If the ship variable already has a value which evaluates to true, then the operator won't do anything. You could also write the statement using unless, but it would be more verbose. This double pipe equals idiom relies on two aspects of Ruby behavior. First, these two shortcut assignments behave in a different way from the rest of the operators. The behavior of ship ||= Spaceship.new can best be modeled as ship or ship = Spaceship.new. So if ship evaluates to true then the second operand doesn't need to be evaluated. However, this conditional assignment works if the ship variable didn't exist at all beforehand. And this is the second quirk of Ruby required for this idiom to work. If I try to run a statement a or a = 10 I get an error because a's undefined, but if I run a || = 10 instead it works. So what kind of magic allows this? It turns out that in Ruby if an assignment appears in a statement the variable is created and set to nil even if the assignment isn't actually executed. Let's try this. B now exists and is set to nil. It even works if I do this. The double pipe assignment works in a similar way. Ruby passes it as an assignment and creates the variable behind the scenes. The only caveat for this conditional initialization is that it doesn't work for Boolean values. Suppose I wanted to initialize a Boolean flag. (typing) When I first run this it looks good, the flag is set but what if I now set the flag to false and then do the conditional assignment again? Hey my flag has been changed to true. This is not what I wanted. The issues that this idiom relies on nil being evaluated as false. Of course false is the only other object that evaluates to false, so when I have a Boolean flag set to false the idiom breaks down.

  25. Flow Control Using and/or I've already mentioned that Ruby has two forms of and and or operators. They are superficially similar so you may be tempted to use the word forms of the operators in conditions. That wouldn't be a good idea because there are two important differences between these operators. One and and or have a much lower precedence than double ampersand and double pipe operators. Two ampersand has higher precedence then double pipe, which is common in other languages as well, but and and or have the same precedence. In the absence of copiers bracket ___ your conditions these differences can lead to surprising results, for example if you tried to put an assignment into your condition. For this reason the accepted practice in Ruby is to use the double ampersand and double pipe in conditional statements, but and and or aren't just a _____ bit of functionality, they do have a purpose. The role of these operators is to provide flow control, let's see how it works. You can use and to chain operations together until one of them returns nil or false. This works due to short circuiting in the and operator. It doesn't evaluate any more operands than it has to. In this example lender.recall will only be executed if the lender is located successfully and isn't nil. Instead you could write this code using if, but the first version is shorter and perhaps clearer as long as you're used to seeing this sort of flow control. You can use or to construct a series of fallback operations. If the first operation returns nil or false try the second one and so on. In this second example if the engine cuts out we try to restart it. If restarting fails we switch to emergency power. The assumption is that engine restart returns true if it succeeds. Using or here is an alternative to using unless. So we enable_emergency_power unless engine.restart succeeds.

  26. Case Statement The next flow control structure I'd like to discuss is the case statement. It allows to choose one of several alternatives based on comparing an object with values. The case statement is quite versatile. In this example I'm performing different actions based on lenders distance from dock. Note that this is a bit contrived and I'm not advocating the use of string values to represent distance. Each of the when clauses is evaluated in turn. There is no fall through between them. Just like the if statement, the case statement can be used as an expression. Here I'm using it to choose a value for thrust power based on distance. This statement can also be written a bit more concisely. Similarly to if I've used the optional keyword then in this example to separate the value compared against from the value being returned. The case statement uses the triple equals operator to compare the values. This fact can be used to dispatch based on an objects class because a class uses the triple equals operator to determine if an object is an instance of that class. By default the triple equals operator does the same thing as the double equals operator. However, it can be overridden to do something else, which is how classes can be compared with objects. In this example I'm performing different actions based on the class of the object given to the case statement. You can also see another feature of the case statement here, the else clause. It gives you the ability to provide a catchall clause when none of the when clauses match. It's particularly useful when you're using the return value of the case statement to assign to a variable, because without else it would return nil if nothing matched. Else gives you a chance to provide some other value. Finally you can use the case statement without providing an object. In this situation you simply specify conditions in each of the when clauses.

  27. Looping Constructs Loops are one of the fundamental constructs in programming so Ruby provides a number of them. However the use of explicit loops in Ruby code is fairly limited. This is because two of the main users of loops are to iterate over collections and to iterate a particular number of times. Both of these can be better done with the help of iterators. I'm going to explain what iterators are, but first let's talk about regular loops as you're still going to use them occasionally. The first loop construct is while. Now this is a pretty familiar looking while loop. If you have a very short loop you can also write the whole thing on one line. The do keyword will help you separate the loop condition from the body of the loop. It works just like the then keyword and if statements. You'd normally use it in single line loops, but not in multiline loops. Ruby has one more trick up its sleeve. Just like with if and unless, while has a modifier form which you can tag onto a statement. Much like if has a counterpart called unless, while has a counterpart called until, which allows you to invert the condition. In this example the ship will continue accelerating until it reaches cruising velocity. Keep in mind, however, that the condition is still evaluated at the start of the loop so the loop body may not execute at all if the condition is true to start with. Until has the same forms as the while loop, it can be written on a single line or as a statement modifier. Finally while and until can be tacked onto the end of a begin/end block as modifiers. The begin/end block is a way of grouping multiple expressions into one expression. It yields the result of the last expression in the group. So end and while and until is almost the same as applying them as modifiers to loop over a single expression, but there's one crucial difference. If you use a begin/end block it will execute at least once even if your condition is false from the start. Ruby provides a for loop as well, but it's not used all that much. Most people prefer to use the each method for iteration. The for loop happens to be syntactic sugar over the each method, which I'll discuss in a minute, but in case you do encounter the for loop, this is a syntax. I is the loop variable and it takes on subsequent values from the collection. A somewhat more common use of the for loop is to iterate over a range. The 1..10 in brackets is a range literal representing the numbers from 1 to 10, which this loop is going to iterate over and print out each number. I'll talk more about ranges along with other standard types in the following module.

  28. Looping with Iterators and Blocks As I mentioned, the for loop uses the each method under the hood. If you call each directly it looks like this. This might look a bit unusual, to understand what's going on here I need to tell you a little bit about blocks. These blocks aren't the same as begin/end blocks you've seen earlier, instead these blocks are a piece of code between two end keywords or between curly braces. And the only way to use them is to pass them as an argument to a method. Some methods like each can take a block as a special kind of argument which comes after any regular arguments. These methods are able to execute the block once or multiple times. By convention the do end keywords I usually used for multiline blocks and the curly braces I used for single line blocks. In going back to the example, I'm giving the each method a block which it will execute once for each element of the array. Methods like this are called iterators in Ruby. In this example I'm using an array but it could just as well be another kind of collection. The result of executing this code will be that the string, This is Serenity, please respond, will be printed three times because there are three elements in the array. The method, which is executing a block, also has the ability to pass one or more arguments into the block every time it's executed. Block arguments are specified between vertical bars at the start of the block. So for example, if I have a method called all in the Spaceship class which returns all instances of Spaceships, I can call each on the ships array and provide it with a block argument, which outputs each ships name. I'll talk about blocks in more detail later in the course. Here is another example of a method that takes a block. If you need an infinite loop instead of while/true you can simply call the method called loop and give it a block to execute. As numbers are objects they can be quite helpful when you need to iterate a particular number of times or work with a range of numbers. For example, you can print numbers from 10 to 20 using the upto method from the integer class. Or you could print the same numbers in reverse using the downto method. The times method repeats the block according to the number it's called on, so this line of code will output the line, This is Serenity, please respond, three times. Finally the step method allows you to loop over a range with a custom increment. This loop will print the odd numbers in the range from 1 to 10.

  29. Controlling Loop Flow Sometimes it's necessary to terminate the loop early, skip a few iterations, or repeat an iteration. Ruby has three different keywords which let you alter the control flow within a loop. There's a break next and redo. They work in explicit loops like while and then implicit iterator loops like each. Let's start with next. Next starts the next iteration of the loop without finishing the current iteration. In this bit of code I'm skipping messages with the type sync. If the current message has a type sync, then next transfers the control flow to the start of the loop and kicks off the next iteration, and message.process isn't executed. Break is a bit like the return statement in methods, it terminates the loop. In this example, the loop is going to process messages until it encounters a message with type voice. When that happens the loop will be terminated. As loops are expressions in Ruby they produce a value. For this reason you can pass one or more arguments to break and they become the result of the loop or the return value of an iterator method. In my second example the loop is going to process messages until it encounters a message with type voice and to that point break will execute and terminate the loop. The message text will be assigned to the text variable. Redo is used to repeat the iteration of the loop. It moves the execution point to the start of the loop without revaluating the loop condition. Obviously it's very easy to create an infinite loop this way, so you want to make sure that execution moves to the next iteration eventually. In the example here, the loop is used to get three positive numbers from the user. The reduce statement is used to deal with invalid input. If the user enters a number which is negative or zero or an invalid value such as a string, the prompt is simply repeated.

  30. Handling Exceptions Whenever you write software you are going to encounter the need to handle errors. The preferred mechanism for error handling in Ruby is to raise and handle exceptions. This is the approach employed by the standard library methods. Exceptions are encapsulated in an object of class exception or one of its subclasses. In order to handle exceptions you need to delineate the segment of code you want to handle exceptions from. Ruby gives you two options for that. One option is to reuse the begin/end block, which you've already encountered when I talked about loops. You can add a rescue clause to this block in order to intercept exceptions. In this example I want to intercept exceptions raised by the batten_hatches method. If an exception is raised the code outputs a message and returns false. By the way this is one of the situations where an explicit return keyword is required. This is so that subsequent lines in the method aren't executed. When an exception is raised Ruby starts unwinding the call stick until it finds an appropriate handler. If it doesn't find one the program is terminated. This is well and good, but in all probability light_seatbelt_sign can also raise exceptions. This is where the other option to define a code segment comes in handy. The rescue clause can be applied to the whole method definition instead of a begin/end block. Here I've added a rescue clause at the end of the method definition. Whether you use a begin/end block or add a rescue clause at the end of method definition, the rescue clause is exactly the same. If an exception from either batten_hatches or light_seatbelt_sign is intercepted, this launch method will return false. If everything goes normally it will return true. When I simply write rescue without supplying any additional details about what I want to intercept, the clause will handle any exceptions derived from the standard error class. Ruby defines quite a few standard exception classes, but these three are the most prominent. Standard error derives from exception and runtime error derives from standard error. So now I can handle exceptions from both methods called by launch, but the message I output is generic. In order to get some details from the exception object, I can give it a name in the rescue clause and then I can output its message attribute. Another useful attribute is called backtrace, it provides the call stick for the point where the exception was raised. What if I want to do something different for different types of exceptions? That's easy, I just need to provide multiple exception clauses. I've added a clause to handle errors from the lighting system specifically. If a seatbelt sign doesn't come on it's not a show stopper for the launch, but I want to output a message about it. Note that I can specify the type of exception without naming the exception object. If you had multiple exception clauses, keep in mind that they are evaluated in order and that subclasses are successfully matched against super classes. This means that you need to put more specific exception types first. Assuming LightError derives from StandardError, if I wrote the StandardError rescue clause first the LigthError clause would never be triggered as light errors would be handled by the more general clause. Since the exception hierarchy starts with the class called exception, you might be tempted to provide a generic exception handler that catches instances of exception, but in most cases it's going to be a bad idea. Such an exception handler is very broad and it will catch things like signal exception or syntax error. Catching single exception, for example, means that the user won't be able to terminate the program using Ctrl C or the kill command and will have to resort to kill-9 or -kill/F if you're on Windows to terminate it.

  31. Raising Exceptions Let's turn to the other side of the equation now. You'll need to raise exceptions in your own code when something unexpected happens. To raise an exception you use the raise method from the object class or its synonym fail. Raise gives you a couple of options. If you use a string as an argument it will raise a runtime error and set the message to the string you pass. You can also specify another exception class to raise in which case the message becomes the second argument. If you need to provide additional information in the exception object you can write your own exception class. If you go down that path it's a good idea to derive your class from standard error to make sure that it's code by default. Raise also has another use. If you use it without arguments within the rescue clause, it will raise the exceptions stored in the special global variable called dollar exclamation mark. This variable refers to the last raised exception. This allows you to do things like log in exceptions and passing them on to be handled by other handlers further up the call stack. You can also decide whether you can handle an exception and if not pass it on to a more generic handler by calling raise. Exceptions: ensure and else Clauses I added a little bit of exception raising code to the batten_hatches method before. Now suppose I'm dealing with a fairly old model of spaceship with a list of doors and other entry points as kept in a plain text file. So this method needs to read the file and go through the records in it to look everything up. Now our batten_hatches method can raise exceptions and the file needs to be closed whether an exception is raised or not. I could add a call to close the file at every exit point in this function, either via a return or via an exception, but it would get messy very quickly. Ruby provides a better solution in the form of the ensure clause. This clause will be executed in every case whether the function exits normally via a rescue clause or via an unhandled exception. The reason I'm checking whether hatch_file has a value in the ensure clause is because file.open can itself throw exceptions and if it does hatch_file won't have a value. The ensure clause has to come after the rescue clauses. Make sure you don't put a return statement in the ensure clause as that will cause any exceptions thrown from the method to be silently swallowed and the return statement will execute instead. As they say in infomercials, but wait there's more. Before the ensure clause you can add an else clause, which will be executed if the section of code you'd intercept an exceptions from didn't throw any exceptions. This section has to come after the rescue clauses but before the ensure clause. The ensure clause is always executed regardless of whether you have an else clause.

  32. Exceptions: Retrying and Rescue Modifier Generally speaking, using exceptions for control flow is a bad idea, but sometimes you can't get around the fact that exceptions will affect your control flow. Here is a somewhat realistic example. Imagine that the antiquated file with a list of hatches, from the previous example, has been replaced with a snazzy restful API which provides this list. The only problem with this is that the API server fails to respond from time to time. In those situations I get an exception from the API. So I'd like to retry the request a few times before propagating the exception out of the batten_hatches method, as it dramatically reduces the number of failures in this method. I could use a loop to do it, but the code is fairly messy. I've got a loop count in request attempts and I also have a begin/end block inside it to intercept exceptions. If the last attempt fails I re-raise the exception so it propagates outside of the method. Instead I could rewrite this code using the retry statement. In this case I no longer have the loop and instead I keep track of the request attempts in the rescue clause. The retry statement is used within the rescue clause and it transfers the execution point back to the beginning of the begin/end block or the beginning of the method. This version of the code has less nesting so it is easier to follow. The discussion of exceptions in Ruby wouldn't be complete without mentioning the rescue modifier which is similar to if and while modifiers. If you add a rescue modifier to a statement it will catch any exceptions raised by that statement which are instances of standard error or its subclasses. If an exception is caught, then the result of the whole expression is the result of the statement following rescue. In my example, if batten_hatches raises an exception the rescue clause will kick in and return false instead. This might seem convenient, but as it catches all sorts of things and quietly provides a value instead, it can _____ errors and make debugging harder. So it's probably a good idea to write your code without this modifier.

  33. Throw and Catch In addition to exceptions, Ruby has a separate throw/catch mechanism. In many other languages throw and catch are keywords used for raising and handling exceptions. However in Ruby this pair is a different flow control mechanism, although its behavior is somewhat similar to exceptions. The way it works is that you put some code, which contains a throw statement, into a catch block. By the way, catch is a method that takes a block as a special argument, same as iterator methods like each. If the throw statement is triggered the corresponding catch block is terminated. The argument of catch and the first argument of throw must match in order for it to work. I'm using a symbol called abort here, but I could use an arbitrary object instead as long as it matches between throw and catch. Getting out of nested loops is the sort of use case where throw and catch may result in clearer code. Catch returns the second argument of throw if it was provided, or nil if it wasn't. If a throw statement isn't triggered then catch returns the result of the last expression in its block. This is why I provided a string saying all samples processed at the end. The result of this program is that if all samples are processed correctly it says All samples processed. If one of the samples failed to process then it outputs the reason for the failure, which was provided as the second argument to throw. Throw/catch even works across method calls. I can extract the contents of the inner loop into a method without any other modifications and this code will still work. At this point you may be wondering whether throw/catch should be considered harmful along with go/to and whether all it does is facilitates spagetti code. The difference between go/to and catch/throw is that catch/throw unwinds the stack properly and then the process triggers ensure blocks so that resources are cleaned up. Granted it isn't something I would recommend to use often, however it might come in handy occasionally when you need exception like nonlinear flow control, but aren't actually handling errors. Also while my example could be refactored so that the inner loop wasn't a separate method and would work fine that way, throw/catch provides an alternative for getting out of nested loops quickly. Finally I should note that catch calls can be nested.

  34. Scope Before I wrap up this module I'd like to draw your attention to scope as the rules in Ruby may be different from what you're used to. While classes and methods in Ruby introduce scope, other constructs such as if/else, loops, and begin/end blocks don't. Any variables you define within these constructs will still be in scope afterwards. However, blocks do introduce scope, so any variables you define within a block won't be visible outside it.

  35. Summary This is the end of module 3. In this module you've become familiar with the variety of constructs for flow control available in Ruby. You've learned how to use various constructs for conditional execution. You've seen how to write loops and how to alter execution flow within them. You found out how to raise and handle exceptions. You've also seen another nonlinear flow control mechanism provided by throw and catch.

  36. Standard Types Overview Hi this is Alex Korban in this module you will learn about some of the types in the Ruby standard library. The Ruby standard library is quite extensive, so this module is only going to scratch the surface of the available functionality. I will tell you about the types you will use in almost any Ruby program you write. Most of these types are also integrated into the language through special syntax _____. I'm going to talk about Booleans, types for representing integer and floating point numbers, regular expressions, strings, symbols, arrays and hashes, and finally ranges. I will also show you how to do parallel assignment.

  37. Booleans Okay the first thing you need to know is that Ruby doesn't have a Boolean type, but you've already seen true and false in the previous module, so what are they? Well true is an instance of true class and false is an instance of false class. They are singleton instances which means that you can't create any other instances of these classes. As I mentioned before, only false and nil evaluate to false in a Boolean context and everything else, including true, zero, empty string, empty array, and so on, evaluates to true. Both true class and false class derive from object. So each of these literals come equipped with a bunch of useful methods. For example, you can convert a Boolean value to a string or check whether it's nil.

  38. Numbers As you've seen before numbers in Ruby are represented by objects. In fact you can think of each number as a label for a corresponding object. You can call methods on both integer and floating point numbers. You're already familiar with methods which help with iterating over a range of numbers, such as times, up to, and down to. I'll talk about integer numbers first. Ruby has two classes to represent integers, they are called fixnum and bignum. Both of them inherit from the integer class. The range of integers represented by fixnum is limited by the machine word size and by the Ruby build that you have. Bignum objects are used for larger integers and are only limited by the available memory. Ruby manages the conversion between these two types automatically. If the result of an operation on two fixnums is outside the fixnum range, then it's converted into a bignum and vice versa. There is a variety of ways to write integer literals, hex numbers start with 0X, octal literals start with a O or a O0, decimal literals start with OD or no prefix, and binary literals start with OB. Negative numbers have a minus in front of them, no surprises there. You can also use underscores to separate groups of digits to make numbers easier to read. Ruby will just ignore the underscores. Let's turn to floating point numbers now. They are represented by objects of the float class and typically have 15 digits of precision. Internally they map to the machine double type. There are two ways to write floating point literal, either simply as a number with a floating point or you can additionally tack an exponent on the end as well. Note that there must be at least one digit before the decimal point and one after. This is required to avoid ambiguity with method calls. You can also use underscores as a separator for groups of digits before and after the decimal point, same as with integers. If you mix floats with integers then Ruby will return a float. There is one aspect of numeric classes which can cause a bit of confusion. Suppose I want to have a function which takes a numeric object and modifies it in some way, I could try something like this. (typing) If I have a variable A, which is an integer, and I pass A to F the function returns a new value, however A itself is unchanged. The reason for it is that objects representing numbers are read-only. Incidentally, this is why Ruby doesn't have increment and decrement operators. So a function like F really doesn't make sense in Ruby, instead you should return the new number and assign it to your variable. Numbers are special in this regard and other objects such as strings and arrays are mutable.

  39. Strings The next type I'm going to talk about is strings. Strings in Ruby are an extremely versatile tool. The string class contains around 100 methods and Ruby also provides several ways of writing string literals. This makes sense if you consider how much programming revolves around processing strings. If we get down to the basics a string is just a sequence of characters with an associated encoding. The characters don't have to be readable, Ruby strings can also be used to represent binary sequences. A string has an associated encoding which is defined by the encoding of the source file it's in. The default encoding is UTF-8, but it can be changed by placing a special comment at the start of the file. The encoding method outputs the encoding of a given string. If I don't specify any encoding then Ruby reports that the string is encoded in UTF-8. I can specify an encoding explicitly by placing the specially formatted comment at the start of the file, if I run this program again, Ruby now reports that the string is encoded in USS key. The comment has to appear on the first line of the file or on the second line if the first line is a shebang. Ruby has several different forms of string literals. Whenever you assign a literal or pass it as an argument, a new object of class string is created. The first option to write a string literal is to use single quotes. Single quotes only allow two escape sequences, if you need to include a single quote in this string proceed it with a backslash. You can also include a backslash by proceeding it with another backslash. Instead of single quotes you can use %q followed by a delimiter. The Q stands for quote, the delimiter can be any known alphanumeric character. If you use delimiters that come in pairs, such as square brackets, then you need to use appropriate opening and closing delimiters. Otherwise Ruby will look for the second occurrence of the same delimiter to indicate the end of the string. This is useful, for example, when you want to insert a number of single quotes in your string, because when you use %q you don't need to escape the quotes. Another option is to use double quotes, they support a what more escape sequences. For example, backslash N inserts a new line, backslash D inserts a tab, and backslash double quote inserts a double quote. Additionally you can insert characters using either their octal code or a hex code. The octal code is preceded by a backslash and the hex code is prefixed with backslash X. You can also insert Unicode, code points, using backslash U. Note that the leading zero's can be omitted. If you need to insert multiple code points you can combine them using curly braces. Double quoted strings also allow interpolation which is a way of embedding results of Ruby expressions into a string. If you look at the strings in this bit of code you'll see that they contain examples of interpolated expressions. Interpolated code is marked with a hash and curly braces. In the first string I insert the value of lander_count via interpolation. In the second string I insert the sum of lander and probe counts. For the most part interpolation is used for single variables or simple expressions, but in theory you can even interpolate multiple statements, although of course that will quickly lead to unreadable code. Interpolation is used a lot in Ruby code as it's cleaner then concatenating strings and will perform better as well because it doesn't require the creation of multiple string objects. It will also automatically convert interpolated results into strings by calling the __S method on them. Instead of double quotes you can use percent capital Q or simply percent followed by a delimiter. The delimiters follow the same rules as when using percent lower case Q. When you use either single or double quotes, multiple literals following one another get concatenated into a single string, so if I type, for example, abc and def, both of the strings are concatenated into one. Literals can also stretch over multiple lines, in this case both new lines and indentation are included in the string. So here I have hello and then I'll insert a few spaces and the resulting string contains both the new line and the spaces. Finally Ruby supports the so called heredoc syntax for strings. This may be useful if you have a multiline string with multiple codes in, for example. The heredoc is denoted with a double less then followed by the terminator. In my example EOS is the terminator. The string ends when Ruby sees the terminator again. The terminator has to be at column one, unless you include a dash after the double less then. With the dash present you can indent the terminator, but in both cases if the contents of the string are indented the indentation is preserved.

  40. String Operators and Methods Let me show you a few interesting string operators and methods. There are a lot more methods available in the string class then I can show here of course, I just want to give you a few examples of the string capabilities. The square brackets operator can be used in a few ways on a string. You can use it to get a character at a particular position, you can also use it to get a substring. In this case the first argument is the index of the start of the substring and the second argument is the length of the substring. Another handy thing you can do is check whether a substring appears in the string, in that case you use the substring as the argument to the square brackets operator. If the string contains the substring then the substring is returned and if it doesn't you get a nil. You can even use this operator to replace the substring with another substring. So for example if I have a string which says Hello Alex, I can replace Alex with George like this. I can go a You can use the multiplication operator to duplicate the content of a string a number of times. The percent operator allows you to produce formatted output. For example you can format numbers to have leading zeroes like this. The first argument to the string is a format specify and the second is the number. So this produces a string representing a number pattern to 5 digits with zeroes. You can also use this operator to limit the total number of digits, so I can type a formatting string like this and pass it a number with a lot of digits. And it's limited to eight digits total. There are tons of other formatting options available as well. The plus operator allows you to concatenate strings, but often interpolation is used instead. Let's look at a few methods now. The string class has methods which return different representations of the contents of a string. For example if I have a string which contains some Unicode like this, I can get an array of characters in this string. I can also get an array of code points representing the string. And finally I can obtain an array of bytes which are used to represent this string. Note that the Unicode code point uses three bytes. The string class also has corresponding iterators called each_byte, each_char, and each_codepoint. You can convert a string to uppercase or lowercase using upcase and downcase methods. (typing) I'll type upcase and then downcase. Like many other methods they have two versions, the exclamation mark version modifies the string object in place and the version without an exclamation mark returns the modified string as a new object. As an aside it's typical for a lot of methods in the standard library to return either the new object or in the case of exclamation mark methods the object they were called on. This allows you to chain method calls which can be very convenient. For example if I have a string with some leading and trailing whitespace I can call strip on this string which will remove the leading and trailing whitespace. And then in the same expression I can call capitalize on it to capitalize the first letter. Another really useful method in the string class is called gsub, it replaces all occurrences of a substring within a string. For example if I have a string containing a bit of HTML I can use a gsub method to replace all the angled brackets with square brackets. Again I'm going to chain it because I need two different replacements. This method becomes a lot more powerful when combined with regular expressions. I'll show you a couple of examples in a minute when I talk about the regular expression class. The last method from the string class I'd like to show you is called split. Split allows you to break a string into an array of substrings based on the separator. So if I have a bunch of numbers in a string separated by spaces, I can call split and it returns an array of substrings because by default it considers space to be a separator. You can also specify a custom separator if you want, so for example if I have no numbers separated by arrows I can call split and give it an arrow as the argument. And again it returns an array of substrings.

  41. Regular Expressions The next thing I'd like to talk about is Ruby's support for regular expressions. Regular expressions are a powerful mini language for analyzing and manipulating strings. The regular expression class is one of the standard types built into Ruby. I'm not going to go over all of the regular expressions syntax as that will probably require a good couple of hours. Instead I'll focus on using them in Ruby code. For a reference on regular expressions syntax you can look up the Ruby documentation for the Regexp class. It's succinct but thorough. Another useful thing is Ruby Mines built-in test tool for regular expressions which you can use to check your regular expressions against input strings. When editing a file in Ruby Mine you can put the cursor on the regular expression literal, hit Alt + Enter, and choose Check RegExp from the menu that pops up. You can then enter sample strings to test your regular expressions. If the sample string doesn't match the regular expression the field is highlighted in red. If it does match then the field is highlighted in green. You can also use an online regular expression test tool at rubular.com. Regular expressions are represented by the Regexp class. You can pass a string containing a pattern to regexp.new. Ruby also allows regular expression literals denoted with slashes. Alternatively you can use %r followed by a delimiter of your choice similarly to %q for strings. The patterns behave similarly to double quoted string literals. They allow interpolation of Ruby expressions the same as cape sequences as well as Unicode characters and sequences. To test for a match between a regular expression and a string you can use the equals tilde operator. The regular expression can appear either on the left or on the right. If a substring of the string operand matches the pattern the operator yields the starting position of the match in the string. Otherwise it yields nil. The exclamation mark tilde operator checks for a lack of a match instead. Instead of a position it only yields true or false. In addition to these operators you can also use the match method to check for matches, which is useful if you want to get more detailed information about the match in the form of an object. This method is a part of the interface of both the string and the Regexp classes. It returns a match data object. Let's look at an example. (typing) M refers to a match data object now, this object has methods called pre-match and post-match which allow you to retrieve the portions of the string before and after the match. You can use the square brackets operators with an index to retrieve the match and any sub-matches defined via capture groups. An index of zero gives you the whole match. And one to three and so on give you the sub-matches. This is best illustrated with a diagram. Given this line of code the match will be 12:13 and m return this substring. m.pre_match and m.post_match will refer to the parts of the string before and after the match. Lastly m in the regular expression. When you use either the match method or the equals tilde operator Ruby also sets a few global variables. Dollar back tick is the fragment of the string before the match. Dollar quote is the post-match fragment. Dollar ampersand contains the match and dollar 1, dollar 2, and so on contain the sub-matches. What if you need to match multiple instances of a pattern within a string? You can apply the scan method from the string class to this job. This call to scan will return an array of matched substrings. You can see in the output that it returns an array containing 12 and 13. The gsub method you've seen before becomes more powerful if combined with regular expressions, particularly because you can refer to capture groups in the replacement string. This line of code is going to return a string with the first and last name swapped and the coma placed after the last name. The \\2 and \\1 in the replacement string refer to sub-matches in the input string. Note that because of the escaping and double quoted strings I had to write backslash, backslash 2 and backslash, backslash 1. I could have used the single quoted string and in that case it would be enough to use one backslash. When I run this you can see that the first and last names are swapped. Gsub can also take a block argument, which is convenient for more complex transformations. For example, if I have a log lines with passwords I might want to replace the passwords with stars. I can do it like this. So here I'm looking for instances of a password in the input string and then I pass a block to gsub, which is going to construct an output string containing the first sub-match, which is the word password, plus a number of stars corresponding to the length of the second match, which is a password itself. When I run this I can see that the password has been replaced with asterisks. Let's move onto the next type now.

  42. Symbols You've already seen a few examples of symbols in the previous modules. For example symbols are used to add attribute accessor methods to classes and to make methods private. Symbols are very convenient once you get used to them and feel very natural to use. So what are they? They are simply a special kind of object, you can think of them a mix between a constant and string. In some other languages enums are used as an alternative to symbols. Each symbol is an instance of class symbol. Symbol instances are only created via literals. A symbol literal is a colon followed by an identifier. Alternatively you can use a colon followed by a string literal. This string literal can include interpolated code just like a regular string. Ruby ensures that symbols are globally unique and immutable. The first time you use a symbol an object is created behind the scenes. Whenever you refer to the same symbol in your program afterwards it's referring to the same object. Symbols are a good substitute for strings when strings are used as labels. An example of this is passing method names to attr_accessor or passing a symbol to a catch block. Symbols are a better option because if you use string literals there's a new string object created every time. Also comparing symbols is simply a matter of comparing object ids, whereas if you have two different string objects their contents need to be compared, which requires more computation. So symbols are more efficient in terms of memory use and performance. They also work great as hash keys as you'll see a bit later. One way to use them is as function parameters where a parameter can be one of a small set of values like sort order or a color from a predefined set or some kind of mode. It's easy to go from a symbol to a string and back. The __s method converts a symbol into a corresponding string. The __sym method of the string class performs the reverse conversion.

  43. Arrays Next up I'm going to talk about another indispensable tool, arrays. Arrays are instances of the array class. An array literal is a sequence of comma separated elements in square brackets. An array stores references to objects and can contain objects of different types. As it stores references you have to be careful when cloning arrays. If you need a deep copy you'll need to implement it yourself. If you simply want to create an empty array typically you would just use an empty array literal rather than array.new. Array.new is used for more complex initialization. You can create an array containing a specified number of elements by passing element count to array.new. All the elements are set to nil, if you want something other than nil, then you can also add the default value as the second argument. However, this only works if the elements are read-only, because each element refers to the same object. Let me show you what I mean. If I create an array with a string as a default value and then I try to convert the first element to uppercase, which I can refer to using the first method by the way. What happens is that every element of the array is converted to uppercase because every element refers to the same object, but don't worry there is a way around this. If I use the block form of new like this, (typing) then every element will be a different object. So now when I modify the last element the other elements remain unchanged. This form of new is also handy when constructing multi-dimensional arrays. With this line of code I've constructed an array containing three arrays of three elements each, in other words, a two-dimensional array. There are convenient shortcuts if you want to create an array of words or an array of symbols. %w creates an array of strings from a string of space separated words. You can use backslash to insert a literal space. Otherwise the available escape sequences are the same as for single quoted string literals. To get the behavior of double quoted string literals, including interpolation, you can use a capital W. Opps let me remove the extra square bracket. So now I have an array containing elements with a tab and you can see that 2+2 is interpolated into 4. There is a similar shortcut for arrays of symbols. For that I need to use %i. (typing) Alright so when you've created an array what can you do with it? It has methods like size and empty. You've already seen that first and last methods X has the ______ elements of the array. You can also access any element using a zero based index and square brackets. Not only that you can also use a -1 based index to access elements in reverse order. This is what I have in the array, -1 is the index of the last element so this returns right. -2 is the index of the second to last element and so on. You can also slice the array using square brackets. This returns a slice of the array starting from index 1 and ending at index 3. This also works if you use a reverse index for either the start or the end of the slice. (typing) The square brackets operator can also be used to set elements of the array. Negative indexes work here as well. In addition you can replace a section of the array. So this is what my array contains now, I'm going to replace the third and fourth elements, so for that I need to type array 2…3 and assign the new elements to it. So now array contains east and west instead of 3 and 4. You can also append elements to an array like this. As you add and remove elements they are able to grow and shrink as necessary. You can join two arrays using the plus operator. You can duplicate the elements using the multiplication operator. If you use a string as a second argument the array will be converted to a string with the second argument used as a separator. The minus operator allows you to delete one or more elements by value. So if I have an array containing 1, 2, 3, 2, 5, and I say minus 2 and 5, then any elements appearing in the second array will be removed from the first array. There are a whole lot more methods available to delete elements, sort the array, and iterate in various ways. It's also easy to use the array as a stack or as a queue.

  44. Enumerable A large portion of these methods comes from the enumerable module which is part of the array interface. In one sentence modules are a way to package a set of methods and constants. I'll talk about how modules work in later videos. For now let's take a look at a couple of examples of what an enumerable provides. In total it has close to 50 methods and this is what turns Ruby collections into power tools. One of these methods is map, which allows you to apply a transformation to each element of the collection. Here I have an array and I'm calling map on it, I'm passing it a block where I multiply each element by 10. The method returns a transformed array. Another interesting method is reduce, which you can use to derive a value from the elements. This line of code sums the elements of the array and returns the result. Map and reduce are a staple of functional programming. Enumerable also includes methods like sort to sort collections and select. (typing) Select returns a portion of the collection containing elements which match the criteria defined by the selects block argument. So with this line of code I'm extracting the elements of the array which are even and that is 2 and 4. Enumerable allows you to iterate over subsets of elements in a few different ways. One of them is using each _cons. So if I have an array like this, I can call each cons with an argument of 2 and print the results. So this bit of code iterates over each block of two consecutive elements in the array. So the first block is 1, 2 then it shifts by 1 and goes over to 2, 3, then 3, 4, and so on.

  45. Hashes Ruby's arrays and hashes are very versatile tools which is partly due to the dynamic nature of the language. Because of this Ruby programmers can use them to represent all sorts of data and don't often need to look beyond these two classes. A hash in Ruby is an ordered collection of key value pairs represented by the hash class. Both keys and values can be arbitrary objects. Keys have to be unique within a hash. A hash literal is marked by curly braces, so this statement assigns an empty hash to h. Inside the braces commas separate each key value pair and arrows point from keys to values. In this hash the string min is the key for value zero and the string max is the key for value 100. As it's extremely common to use symbols as hash keys there's a special shortcut syntax for that. The colon migrates from the start of the symbol name to the end and replaces the arrow. If you have a hash you can access its elements by a key using the square brackets operator. You can think of hashes as arrays with arbitrary object indexes instead of integers. You can also replace a value this way. This is also how you add elements, so if you use a key which is not already in the hash a new element will be added. Now if you use a key that isn't in the hash to get an element, like this, by default you will get a nil. However, similarly to the array instantiation you can specify a different default value when constructing the hash using hash.new. So if I type h=hash.new0 and try to get an element that isn't there, instead of a nil I get zero. Same as with arrays, this means the same object reference is returned every time. If you want different objects to be created every time you can use the block version of the new method. You can iterate over the elements of a hash using each. It looks like this. Let me just put some elements into this hash and when I try this again you can see that it iterates over two element arrays consistent of a key and a value. You can also separate the key and the value out if you list two arguments in the block. So if I list k and v, I can output them separately. As I mentioned, hashes are ordered so each lists the elements in the order they were added to the hash. Like array, the hash class includes the enumerable module so all the methods available for arrays are available to hashes as well, although in this case they will operate on two element arrays instead of single values.

  46. Ranges The last type I'd like to talk about is ranges. The range class objects can be created via literals. A literal is two objects separate by either two dots or three dots. Two dots indicate an inclusive range with the upper boundary included and three dots means that the range is exclusive and the upper boundary isn't part of it. If you want to call methods on the range literal you need to enclose it in brackets so that all the dots don't confuse Ruby. The range class doesn't have a whole lot of its own methods, it's got methods like begin and end, which allow you to get its boundaries. And it also has include which allows you to test if a particular value is part of the range. There are a few other methods as well, however, the range class also includes the enumerable module so it does end up providing the reach interface and allows you to do things like this. (typing) As you can see when you call map on a range, map iterates over the array representation of the range and returns an array of 10 elements. You aren't limited to just integer ranges, you can create ranges of string values, you can also create ranges of floats, however in this case you won't be able to iterate over them. I also want to mention that ranges can be used in a case statement. This works in the same way as dispatch and waste on the class of an object in a case statement. The range class has a custom implementation of the triple equals operator, which checks whether the supplied values within the range. In my example the case statement will check whether sample reading falls within either of the ranges and outputs a string correspondingly.

  47. Parallel Assignment Parallel assignment and the splat operator are related to the standard collection types, so let's give them some attention in this module as well. Parallel assignment allows you to assign to multiple variables in a single statement. The result of this statement is that a is equal to 1 and b is equal to 2. If the right side of the assignment is a comma separated list, it's converted into an array and then its elements are assigned to variables on the left. A side effect of parallel assignment is that if you assign a comma separated list to a single variable, that list is converted into an array. The right side of parallel assignment can be an actual array. This works especially well when you have a function returning multiple values in an array. You don't need to create a temporary array if you assign the elements to variables directly. Because the function returns an array with 1 and 2 as the first elements, once again a is assigned 1 and b is assigned 2. The rest of the elements are discarded. What if you want to assign only some of the returned elements to variables? For example, I might only want to assign the first and last elements from the returned array. What about the other two elements? There's no way to skip them, so I have to use a dummy variable. Instead of coming up with a dummy name, you can use underscore. Underscore is mostly a normal variable except it's treated in a slightly special way by the interpreter. If you run the Ruby interpreter with a -w argument it will output warnings, including warning you about unused variables. If you use underscore or any variable name starting with an underscore in your parallel assignment, the unused variable warning will be suppressed. Parallel assignment can be combined with a splat operator which is represented by an asterisk. One of the values on the left can have the splat applied to it. This value will accumulate as many elements as possible in the form of an array. If the last variable on the left has a splat, then it will accumulate the remainder of the elements from the right. If it's not last, it will behave in a greedy manner leaving just enough elements for the following variables. So in this case a will be assigned 1, b will contain an array with 2 and 3, and c will be assigned 4. The splat can also appear on the right-hand of the assignment. In this case the object it's supplied to are converted into arrays which have their elements expanded in line. For example, you can use a range to assign elements from a sequence to variables. So, for this line of code a, b, and c are assigned 1, 2, and 3. You can also make an array a part of the sequence. In fact, you can simplify the last assignment by using a splat by itself instead of the dummy variables. As you can also see in this example, the splat can appear both on the left and right sides of one assignment. The splat operator has another use outside of parallel assignment. If I use the splat operator on the range inside an array literal, the range is converted into a series of elements which are inserted into the array. It also works on hashes. If I use a splat on a hash inside an array literal I get an array containing two arrays representing keys and values. In fact, the splat operator will work on any class that implements a __a method. To illustrate this I've written a __a method in the Probe class which returns an array of all its attribute values, such as name, type, and size. I then use the splat operator to convert the instance of the Probe class into an array. When I run this you can see that the result is the series of elements returned by __a.

  48. Summary This is the end of module 4. In this module I've shown you the most common standard types and some of their methods and operators. I talked about Boolean values, numbers, and strings. I showed you regular expressions and symbols. I also discussed collection types, arrays and hashes, as well as ranges and the enumerable module which makes this collection so powerful. Finally I explained how parallel assignment works in combination with the splat operator.

  49. Methods in Depth Overview Hi, this is Alex Korban in this module we'll have an in-depth look at writing and using methods in Ruby. You've already seen a lot of methods in the previous modules, however, they are really simple, taking just one or two arguments. Ruby has a lot more method features and in this module I'd like to get into the intricacies of defining and calling methods. I will show you how you can provide default values for method parameters. You will find out how to write methods which take a variable number of arguments. I will explain how you can add named arguments to your methods. I'll talk about creating method aliases and overriding methods. You'll see how operators and operator overload work in Ruby. I'll explain the method calls as messages model Ruby employs. Finally, we'll delve a little bit into metaprogramming when I talk about the method missing method.

  50. Default Parameter Values Ruby doesn't allow you to define two methods which have the same name, but different parameter lists. When you need to provide a flexible interface that doesn't require specifying all the arguments every time, you can use default arguments instead. Suppose I have an in orbit spaceship factory which can produce spaceships to order. I can have a produced spaceship method which looks like this. The default values for parameters are specified in the function definition with an equals sign and an expression after the parameter name. The expression isn't limited to a simple value and can include preceding parameters, method calls, or even conditional logic. The default values are calculated at the point of method call, not at the point of method definition. The optional parameters don't have to be at the end of the parameter list. If there are required parameters following a group of optional parameters, Ruby will correctly use default values if you pass fewer than the maximum number of arguments in. In this example, engine_count is a required parameter, which falls to optional parameters. When I call produce spaceship with one argument, that argument is used as the value of engine_count. However, you can't intermingle required and optional arguments arbitrarily. You'll get a syntax error from the interpreter if you do.

  51. Variable Length Parameter Lists Sometimes you will need more than just a couple of optional arguments. For some methods its useful if they can take an arbitrary number of arguments. You could always just pass in an array, but Ruby has nice built-in syntax for methods taking a variable number of arguments courtesy of the splat operator. For example, if I want my spaceship factory class to have a method which produces a whole fleet containing different types of spaceships, I can write it like this. The first argument will be assigned two days to complete and the rest will become elements of the array assigned to types. When I call this method, days to complete will be set to 10 and types will be an array containing symbols freighter, freighter, and explorer. The array argument doesn't have to come last in the parameter list, in fact the parameter list with a splat works in the same way as a list of variables on the left-hand side of a parallel assignment. I talked about parallel assignment in detail in module 4. The array parameter collects arguments in a greedy manner leaving just enough elements to assign to the following regular parameters. An array parameter can be combined with default parameter values. Optional parameters have to come before the array parameter. The arguments passed to the method are first used to provide values for optional parameters and after that any remaining arguments are assigned to the array parameter. So here I have a method which has a default value for the first parameter and the second parameter is an array parameter. You can call this method without arguments or you can explicitly provide a value for the first parameter, followed by any values for the array parameter. However, you can't just omit the first argument, as days to complete will always be set to whatever you pass as the first argument. You can also use the splat operator when calling the method. Its effect is to convert the argument it's applied to into an array by calling the arguments two underscore A method. After that the elements of the array are inserted into the argument list. As a result, the first call to produce fleet is equivalent to the second call. The mechanics of the splat operator in method calls are the same as when you use a splat on the right-hand side of a parallel assignment.

  52. Keyword Arguments When method parameters start to multiply the code can easily become hard to understand. When there's more than one argument it's not exactly obvious what each one of them represents. To improve this situation Ruby has keyword arguments. When calling the method with keyword arguments you don't just provide a value, instead you need to include the argument name followed by a colon and then the value. The definition of a method with keyword parameters looks quite similar. The parameters are required to have default values. If any of the arguments aren't passed to the method the default values are used instead. As keyword arguments can be distinguished by name, they can be supplied to a method in a different order from how they are initially defined. They can also coexist with regular parameters as long as regular parameters come first. In this example, the first parameter is just a regular parameter with a default value, while size and engine_count are keyword arguments. Normally if you tried to pass a method some keyword arguments which aren't in its definition, you'll get an error. However, if you add a double splat parameter to the end of the parameter list in method definition, it will collect any keyword arguments which weren't explicitly listed in the definition. The double splat parameter will be assigned a hash of these arguments. I can use this, for example, to allow my method to take an optional speck of custom components. In the implementation of this method I have the standard component speck in the components hash. I then merge this hash with custom components. The merge method works in such a way that values with duplicate keys will be overridden by values from custom components. As a result, I can call this method and specify any components I want to deviate from the standard speck. In this call I specified engine upgrades and nice leather seats for my yacht. Instead of specifying all the keyword arguments directly in the method call, you can first construct a hash and then pass it to the method. Similarly to using a splat operator to splice array elements into the argument list. You can use the double splat operators so that Ruby creates the variable it's applied to as a hash and combines it with any other keyword arguments. This about covers it for method definitions.

  53. Method Aliasing The next feature I'd like to talk about is method aliasing. It's useful when you're overriding a method, but want to be able to access the old version. If you're overriding a superclass method you can use super to call the superclass method, but if you're monkey patching a class you need aliasing. The method called alias_method allows you to create a copy of a method with another name. For example, if I modify this string class to print strings with extra _____, I might also want to override the size method so it reports the new size. However, I want the new size method to refer to the original size. To achieve this I can call alias_method to create a copy of the size method called original_size. Alias_method can take either symbol or string arguments. I can then override the size method and have it call original size. So alias_method allows me to override a method while retaining access to the original version. Let me run this just to check that it works correctly and you can see that it reports 5 as the string size.

  54. Operators I'd like to bring your attention to operators now. It's no accident that I'm talking about operators in this module. As you've already seen in previous modules, Ruby allows you to define your own versions of some operators when writing a class. The reason for it is that most operators are in fact methods they just have a little bit of syntactic sugar on top, so using them doesn't look like calling methods. The exceptions to these are the logical operators, &&, ||, and, or, not, and the ?: operator. The assignment operators aren't methods either. Everything else, such as the square brackets operators, comparison operators, mathematical and bitwise operators are methods and as such you can either add your own implementations of them or override standard implementations. Let's look at few examples. I'm going to go back to my trusty Spaceship class and add a few operators to it. First I'm going to add the index operator. (typing) I'm going use it to get and set different types of vessels stored within the spaceship, these include landers and probes. There are actually two parts to this operator, the square brackets operator returns a value based on an index object. My implementation passes the type to the vessels hash and returns whatever is stored at that key. The second part is the square brackets equals operator. This operator returns a value which can appear on the left side of an assignment. It takes an index and a value to set as its arguments. My implementation takes the vessel type and an array as its arguments. The array goes into the vessels hash at type key. I can now use these operators like this. So I can use it to add some lenders and then I can have a look at the lenders on board the spaceship. So when I run it I can see that two lenders have been added to the vessels hash. I can also add an append operator to my spaceship to allow me to put cargo on board easily. This operator simply adds the cargo object to the cargo array instance variable. I can use it like this. So here I have a dummy class called CargoPod, I'm going to create an instance and then I'm going to add that to the cargo bay of the spaceship. Let's just check that it works, so in the output I can see that there's now a new item in the cargo instance variable. Another interesting operator I'd like to show you is coincidently called the spaceship operator sometimes. This operator is used to make objects sortable. This operator compares two objects and returns zero if they are equal, -1 if the first is less than the second, and 1 if the first is greater than the second. In my case I want to sort spaceships by name so I can delegate to the string operator. Now that I have this operator in place, I can sort an array of spaceships. Let me just add a couple more spaceship instances and then I'll put them in an array, sort them, and output the names. Let's run this and see what happens. You can see that they are sorted by names now. While I'm at it I'm also going to show you how to implement unary plus and minus operators. In order to distinguish them from the binary versions they have @ added to their name and of course they don't take any arguments. By the way, binary operators such as plus or less than only take one argument as self if the implicit left-hand side argument. Going back to my unary plus and minus I'm going to use them to increment and decrement the ships speed. And then I can use these operators like this. Let's run this, you can see that speed was first increased to 10 and then reduced back to zero. The last operator I'm going to add to the Spaceship class is the not operator. I'm going to use it to initiate the self-destruct sequence as I'm going to have no ship after invoking this operator, there is some logic to this. Obviously I can no longer use the operator in a Boolean context as it does something completely unrelated now. This is how I can use it, it's no longer going to work in a Boolean context. When I run this I can see that the operator output self-destruct sequence initiated. The plus/minus and not operators in my Spaceship class actually illustrate an important point. It's easy to get carried away and get to clever with operator overload at the expense of clarity. The code with custom operators can look quite cryptic to someone who's not familiar with the exact semantics of operators in your class and can even behave contrary to normal expectations as in the case of the not operator that I've added. For this reason my advice is to use operator overload in sparingly and only in those cases where it makes the code more readable.

  55. Method Calls as Messages Now that we've explored all the syntactic nooks and crannies related to methods, let's focus on the semantics for a bit. Using an idea borrowed from small-talk calling a method in Ruby is done by sending a message with the method name and parameters to an object. The object then looks up the corresponding method and if it finds it, it executes it. So you can also think of methods as message handlers. For this reason the object you call a method on is sometimes called the receiver. This aspect of object semantics is actually visible. The object class has a method called send which allows you to send a message as a symbol along with any parameters. I've already mentioned this method when I showed you that you can call a private method using send. This can be really convenient and can cut down on boiler plate code. For example, if you have methods which are executed in response to user input, instead of writing a potentially unwieldy case statement to decide which method to call. You can create a hash, associate an input with a method, and your dispatch code will be reduced to a single statement. If you happen to implement a method called send for your own purposes in your class, you can also use sends alias called __send__ to send messages instead. This can be handy as send is a common method name. We've established that method calls need a receiver, but what about methods I was defining at the start of the course which weren't even a part of any class like double. I'll clear this up in a minute. First, let's recall that you can make method calls without an explicit receiver. When I call batten_hatches inside the launch method it's called on self which is the implicit receiver. It turns out that a similar thing happens to methods which are defined outside of any class. Every Ruby program has a default object called main. Outside of any other context, self refers to main. The class of self is object. When you add a method like double it's added to the object class, which makes it available everywhere throughout your program. When you call your method it's called on self, just like batten_hatches inside the Spaceship class, except in this case self happens to be the main object. So in Ruby there is no such thing as free methods. What about methods like puts, be, arrays? They are also part of the object class because it includes a module called kernel where these methods are defined.

  56. method_missing So far you've seen that a method call in Ruby means that a message is sent to an object and then the object looks up the method in its class, or one of the super classes, and calls it. So what happens when you send a message to an object and it can't find the corresponding method? The obvious effect is that you get a no method error, which tells you that the method is undefined, but there's more going on here than meets the eye. When Ruby goes through the class hierarchy and doesn't find a method, it invokes a method called method_missing. The default implementation of this method, defined in the basic object class, raises the no method error exception. It's possible to override method_missing with your own implementation, which does something different. For example, let's consider that I'd like to provide a convenient interface for locating cargo on board my spaceship. I'd like to be able to write things like cargo.find_by_destination and cargo.find_by_size and perhaps even cargo.find_by_weight_and_volume. The cargo has a number of other attributes such as origin, classification, and so on. I'd like to be able to use those attributes and their combinations as well. The first, very tedious, option I have is to write each and every method by hand. The second option is to change the interface so that I have only one method called find which takes keyword arguments with attributes. However, if I really want the interface which encodes attributes in method names, it's also achievable. Suppose I have a private method called find in my cargo class which takes a hash of attributes and values and returns the precise cargo location in the hold. In order to have an interface like the one I showed you before, I need to provide an implementation of method_missing, which is something like this. (typing) This method receives the name of the method which is invoked along with any arguments. I can match the name against a couple of regular expressions. First I look for a name which contains two attributes. I then construct a hash and pass it to the generic find method. There's a small trick I'm using here to make the code a bit cleaner. When you pass a hash as the last argument to a method you can omit the curly braces which is what I've done. The second when clause looks for methods with a single attribute in the name. Finally in the else clause I defer to the default implementation of method_missing, this is quite important. If I don't this is what happens. Let me call a method which doesn't exist and doesn't match by method_missing. When I run this everything looks fine. The method call to a nonexistent method is silently swallowed. If I uncomment the else clause however, and then run this again, then I get a no method error which will help me find the source of the problem instead of me just sitting and wondering why my method wasn't called. For similar reasons the general practice is to define a white list of allowed methods in method_missing instead of a black list of things which aren't allowed. I'd also recommend to use this mechanism sparingly, as it can quickly become hard to debug. It can also cause performance issues if there are a lot of calls routed through it. Okay let me remove the method call that causes an error. One thing that's not quite right about the cargo class is that if I tried to check if it responds to a particular find in method, for example, if I try to check whether it responds to find by destination, I'll get a false. This is because respond to knows nothing about my method_missing exploits. The solution is to override the respond to method as well. So let me paste my implementation of respond to. I need to make sure that it returns true if the method name matches the find a method name and pattern. So now if I add another check for a nonexistent method, I can see that it works properly. I get true for a method that's handled by method_missing and I get false for a method that isn't. Method_missing is one example of the metaprogramming facilities in Ruby. As you've seen the behavior of this program is no longer simply determined by the data or other inputs feed into it. It's also affected by the code itself. The names of the methods invoked during the program alter the control flow within it. There are lots of other metaprogramming facilities available. For example Ruby also has const_missing, which is the counterpart to method_missing for constants. It's also possible to add methods to classes at runtime as well as remove them. When that happens Ruby runs hook methods which you can override to do something useful. Another example of a hook method is a method called inherited which is executed every time a subclass of your class is created. I won't go into more detail about metaprogramming as it's beyond the scope of this course. I hope this short introduction gives you an idea that when your code starts getting unwieldy and you're looking for an elegant solution, Ruby has more to offer than just run of the mill object oriented features.

  57. Summary This is the end of module 5. In this module you learned the ins and outs of defining and calling methods. You found out about default parameter values, keyword arguments, and creating methods with a variable number of arguments. You've seen how you can alias methods. You've learned that most operators are simply methods and can be overridden to suit your needs. I showed you that method calls are messages passed between objects. Finally you dipped your toes in metaprogramming when we explored method_missing.

  58. More Ruby Tools: Blocks, Constants, Modules Overview Hi this is Alex Korban in this module I'll go into more detail about some of the language tools I mentioned in the previous modules. There are three more language constructs I need to talk about to give you the full picture of the Ruby language. The first one is blocks along with their cousin's procs and lambdas. I've already introduced blocks, but in this module I'm going to provide you with the details. The second construct is constants. The third thing I want to discuss is modules which are an essential part of the object orientation model and Ruby's answer to the complexities of multiple inheritance.

  59. Blocks I've already introduced blocks when talking about the iteration constructs available in Ruby. As a reminder, a block is a piece of code between two end keywords or curly braces. By convention, the two end keywords are usually used for multiline blocks and the curly braces are used for single line blocks. The only way to use blocks is to pass them as an argument to a method. Some methods can take a block as a special kind of argument which comes after the regular arguments. Methods are able to execute the code in the block once or multiple times. A method can also pass arguments into the block when it executes it. Block arguments are specified between vertical bars at the start of the block. So far I've been using blocks, but I haven't shown you how to write a method which can take a block argument. Let's rectify this. In the simplest case you can just use the yield keyword to execute the block at some point in your method. For example, I could write a method which takes a block of code and executes it only in debug mode. Let's go over this method line by line. The first line aborts the execution if the debug mode isn't on. The second line uses the block given method to check if a block has been passed to the method, if not the method returns nil. The third line produces some output and finally the last line is the yield keyword, which executes the block. I can call the debug only method without arguments and it will do nothing. If I pass in a block it will be executed as long as the debug mode is on of course. If a block requires arguments you simply pass them to yield. For example, I can pass some debug attributes into the block instead of exposing them in the interface of the class. Using yield is similar to a method call. The value of yield is the result of executing the last expression in the block. Block arguments are similar to method arguments. They can have default values, you can use keyword arguments, as well as specify array arguments using the splat operator. Here I've got a block which has all possible types of parameters. I invoke the block with a set of arguments within the produce method. When I run this program you can see that these arguments are correctly assigned to variables within the block. I don't expect that you'd use such complex block parameters in your everyday work, but having parity with methods on this front is useful as it's possible to use blocks when defining methods dynamically.

  60. Block Local Variables There is a subtlety in Ruby's behavior when a variable within a block has the same name as a variable in the outer scope. Block arguments shadow variables with the same name in the outer scope. However, if you attempt to define a variable in the block body which has the same name as a variable in the outer scope, you'll run into a problem. In that case instead of creating a new variable you're going to override the value in the existing variable from the outer scope. The solution is to declare your variable as a block local variable in the block argument list. You do it by listing any variables you want to be local after a semicolon in the argument list. Let me illustrate this with an example. Here I have my Spaceship class which has a variable called debug attributes, which is a hash. I put two attributes in it called temperature and containment_status. I also have the debug only method, from the previous examples, which passes the debug attributes hash to the block it's called with. I've also written a locate_cargo method which sets up a local hash with attributes and then it calls the debug only method with a block. The block modifies its argument. When I run this program and it executes the locate_cargo call, you can see that the block modifies its argument, not the attributes hash defined in locate_cargo. This shows that block arguments shadow same name variables from outer scope. However, if I now try to define an attributes hash within the block, and I have to rename the block argument, and when I run this you can see that this time the block overrides the contents of the attributes hash. To resolve this I need to declare it as a block local variable. I do this by adding a semicolon and listing my variable in the block argument list. When I run this now I can see that there are no changes outside the block.

  61. Using Blocks An important property of blocks is that they are closures, well almost. They carry their context with them, this includes local variables, class variables, constants, and the value of self. A block executes in this context. Normally this is very convenient as you don't need to pass in everything as arguments. For example, here I'm printing the debug attributes hash in the block. This hash is stored in the debug attr's instance variable, I don't have to pass it in as a block argument, and it doesn't need to be accessible outside of the class. As the block is defined inside the class it's able to access the instance variable. The only non-closure like aspect of blocks is that if a block contains a return statement it's executed in the scope the block was defined in. This can be problematic because that scope may no longer even exist by the time the block is executed. In this file I define my Spaceship class and it has the debug only method from the previous examples, and then I made the misguided attempt to limit block execution to a particular instance of spaceship by returning if the name isn't right. When I run this code I get an error. This is because the return is executed in the outer most scope, not within a method. The reason for it is that the block was defined in the outer most scope. Another issue to look out for is memory use. Blocks carry their context with them and it can prevent large objects from being garbage collected as they are still referred to by the block. Blocks are an extremely useful feature. In addition to allowing you to factor out common code into methods they also enable iterator methods which are a powerful alternative to regular loops. They also provide other possibilities for cutting down on boiler plate and making code clearer. As an example a common Ruby idiom is execute around. If you want to be able to time the execution of some pieces of code, for example, you could do it like this. This method records the start time, then executes the block, and then calculates the time it took to execute the block. I can then define a couple of operations and then I can run them in a block passed to the with_timing method. The same approach works for logging before and after a group of statements. Another variation of this idiom is transactional code, for example, you might want to ensure that the file is closed after being processed. Or you might want to model wrapping a bunch of database queries in a transaction. Both of these things are easy to implement with blocks. This example shows how to implement transaction support. The transaction method executes a block but the execution of the block is wrapped in a begin/rescue/end clause. If any of the statements in the block raise an exception the transaction is rolled back. If everything goes well the transaction is committed. I can then call this method and pass it to block which does multiple queries of the database and they will be wrapped in that transaction. However, blocks also have limitations. You can only pass one block to a method. You can't pass it on from the method that's called with a block to another method. And what if you want to pass the same block of code to several methods? You have to duplicate it and it's not going to be very dry. If only blocks were objects, like most other things in Ruby, it would solve these issues.

  62. From Block to Proc It turns out that you can give a block a name in the method parameter list. In the example here the block is given the name block. Note the ampersand before the name, it tells Ruby that this is a name for a block, not a regular parameter. Once you have a named variable you can check what its type is. Let's run this code to find out what it is. The output tells me that the block variable is an instance of class proc, I'm going to refer to this instance as a procs for now on. A block isn't actually a proc, but it can be converted to one, which is what I've done by prefixing its name with an ampersand in the method parameter list. Naming a block parameter isn't the only way to get a proc. You can also create proc objects directly by passing a block to proc.new. Alternatively you can use the kernel method proc included in the object class to create proc instances. The proc method is simply an alias for proc.new. There are several ways to execute the code stored in the proc, you can use call or yield methods, you can also abbreviate it to a dot followed by a parameter list in parentheses. Finally, you can use the square brackets. Now that you have the ability to convert blocks into named objects, it's easy to pass them between methods and refer to them via variables. It's now easy to implement things like callbacks _____ initialization. All you need to do is store the broken and instance variable and call it at a later point when you need to invoke a callback or run some initialization code.

  63. Lambdas Procs aren't the whole story however, there is another way to convert a block into an object. The object class method lambda takes a block and converts it into a proc object. While this object is also an instance of the proc class, it behaves in a somewhat different way, which I'll tell you about in a second. Before I do that, I'll also show you the alternative syntax for creating lambdas which you might find more convenient. This is sometimes called a _____ lambda because of the arrow. Note that the parameter is now listed outside of the blog buddy. You can't have spaces between the arrow and the parameter list, otherwise you'll get a syntax error. So why does Ruby have both procs and lambdas in addition to blocks? Let's look at the differences between all three. In general, procs behave similarly to blocks, their purpose is still to allow you to drop code into a method, but you get more flexibility because they are named and can be passed around like a regular object. Lambdas are more like anonymous methods. Now lambdas are strict about their arguments. The return and break statements and procs and lambdas behave differently, however, next behaves the same in all three cases, it simply returns control back to the caller of the block, proc, or lambda. Let's look at the differences in a bit more detail. The difference in argument handling between procs and lambdas is that if you pass too few or too many arguments to a lambda you will get an exception. Procs and blocks, on the other hand, are relaxed. If you pass too many arguments they discard what they don't need. If you pass too few they fill in the rest with nils. A return statement in a block or a proc is executed in the scope in which the proc was defined. As I mentioned earlier this may be problematic because that scope may no longer even exist when the proc is executed. This can happen, for example, if you pass a proc from one thread to another. A standalone break statement, which is outside a loop, isn't allowed in a proc. This is in contrast with a regular block where you can use it. So as a general rule, you shouldn't use either return or break in procs and it's probably a good idea to avoid the return statement in blocks too. If you use a return or a break statement in a lambda it simply returns control from the lambda to the call in method. In this situation the lambda behaves much like a method.

  64. Using Procs and Lambdas Now that you've learned how to convert blocks into objects, let's look at a couple of interesting things you can do with these objects. You can check the number of arguments the proc or a lambda expects using the arity method. If it expects a fixed number of arguments the method tells you how many. So in the first example it's going to return 2. If some arguments are optional then it returns a number of non-optional arguments plus 1, but with a minus sign. In the second example the block has two non-optional arguments, so the method returns 2+1 which is 3 with a minus sign. The proc class also implements the triple equals operator. This operator executes the code stored in the proc. This allows you to use procs and lambdas in a case statement. So in this example I have two procs, one that determines whether a given time falls on the weekend and another that determines if it falls on a weekday. When I use them in the case statement the current time is passed to each proc and if it returns true the appropriate output is produced. One more useful trick to know about is that Ruby can convert symbols into procs. In order to explain how it works I have to backtrack a little bit. Suppose I have a method which can take a regular parameter and a block. This is a method I have here. When I call it with a proc object as a parameter it's passed in as a regular parameter just like any other object. However, I might also want to pass it in in place of a block. In that case I can use an ampersand in front of it to tell Ruby to treat it as a block. When you use the ampersand Ruby not only puts the object into the block slot and the parameter list, but it also attempts to coarse the object into a proc, if it isn't already a proc. It does that by calling the two proc method on the object. Suppose you have an array of strings, if you want to convert these strings into uppercase, you can put the map method to work. (typing) This statement tells Ruby to iterate over the names array, call up case on each element, and return the array consisting of the results, but there is also a shortcut for this type of operation. You can achieve the same result like this. (typing) So instead of passing a block to map you're just giving it a symbol and telling it to treat it as a block. Obviously, calling up case isn't a proc it's a symbol. Because I used the ampersand on a symbol which isn't a proc, Ruby is going to apply the corrosion rules and it's going to call the __proc method on the symbol. The symbol class happens to have a two proc method, this method returns a proc which takes an argument and sends the symbol to it as the name of the method to call. Which is exactly the same as what I did when I passed a block to the map method beforehand.

  65. Constants The next thing I'd like to discuss is constants. While some of the rules normally reserved for constants are played by symbols in Ruby, constants still have their place when you need something that refers to an actual value. A constant is similar to a variable in that it's also referenced to an object. Constant names in Ruby start with an uppercase letter. It's typical to name them in all uppercase letters with words separated by underscores. As a matter of fact, class names are constants and that's why they start with an uppercase letter. A constant is created simply by assigning a value to it, just like a variable. Like many other things in Ruby, constants aren't strictly enforced. If you have a constant you can assign a different object to it and you'll just get a warning. For example, I defined a constant here and now I can assign a different value to it. You can also modify the object the constant refers to. (typing) So here I'm adding another element to the array and Ruby has no problem with it. The reason for this is that there might be other variables referring to the same object so it can be modified anyway. It is possible to prevent an object from being modified by calling the freeze method. However, it's used very infrequently in practice. After calling freeze if you call a method that modifies the object you'll get a runtime error exception. So let me freeze my types, object, and then attempt to add another element to it. This produces a runtime error. Once an object is frozen you can't unfreeze it, you can check whether a given object is frozen by calling its frozen method. Note however that while you can't call any methods that modify the object itself, you can still modify other objects it refers to. For example, if you freeze an array you can't replace an element with a different object, but you can modify the element. So I can convert the element that I have in my array into uppercase. One more thing I need to talk about is the scoping rules. If you define a constant outside a class or module it's going to be accessible everywhere throughout the program. If you define it inside a class or a module you can access it anywhere inside that class or module. However, if you need to access it from the outside you'll need to use the scope resolution operator, which is a double colon, along with the class name. Let me define a constant within a class. If I tried to access it by simply using its name, I'm going to get an error. I need to qualify its name with the class name. Incidentally you can also use this operator to add constants to a class from outside the class. So I can add another constant called MAX_SPEED to this class like this. The last thing I should mention is that you can't define constants inside methods.

  66. Modules The final part of this module is about modules. Modules are similar to classes, but with one key difference, they can't be instantiated. A module is defined using the module keyword. A module can contain methods, constants, classes, or other modules. Modules serve two distinct purposes in Ruby. The first one is name spacing. For example, I can put all API related methods into the API module. Note that in this situation methods need to be added as module level methods, which is done by prefixing their names with self.. You call them in the same way as class methods. If you place classes into a module you can access them like any other constants using the scope operator. Modules can also be nested if you require more complex code organization. So here I put the API module into the spacestuff module and then I can access the API module with the scope resolution operator. The second purpose of modules is to mix into classes and thus add functionality to them. These modules are called mixins. One example of a mixin is the enumerable module I mentioned previously. Mixins are included in classes and a class can include multiple modules. This is Ruby's alternative to having multiple inheritance. Mixin modules still act as wrappers for a reusable set of methods, constants, and so on, so they are largely the same as the modules we've already discussed. The main difference is that mixins typically contain instance methods while namespace methods don't. Once you've written the mixin module you need to include it in your class. When you've included a module, or mixed it in in Ruby terminology, its instance methods become available as instance methods of the class. So once I've included the AirControl module in the Spaceship class I can call the measure_oxygen method from it on a ship instance. The way this is implemented is that modules are slotted into the inheritance hierarchy. The order in the inheritance diagram on the right is significant. Modules become the most immediate ancestors of the class. When Ruby looks up methods, it's going to start with modules and then look further up the inheritance chain. Also if two modules contain a method with the same name, then the version included last is going to win out. By the way, module inclusions are inherited along with the rest of superclass functionality. Remember that when I talked about duck typing I mentioned that it allows you to simplify your class hierarchies as you don't need to factor out ancestor classes for the purpose of defining interfaces. Mixins also simplify class hierarchies and give you the ability to write loosely coupled code. Instead of factoring out common functionality into a superclass, you can place it into a module and include it where you need it. It's also possible to incorporate instance methods from a module into a class as class methods. To do this you need to call extend instead of include. The instance methods in the module then become available as class methods. As both extend and include act on instance methods in a module you can't inject a mix of class and instance methods into a class. A common workaround for this is to wrap the class methods in a class methods module. You then include the main module and extend the class methods sub module. As it's somewhat common for mixins to contain both instance and class methods, there's a common trick to spare you calling both include and extend. You can provide an implementation of the hook method called included in your module and call extend from there. This method is called whenever the module is included in a class. With this in place it'll be enough for you to call include in your class to mix in both instance and class methods. What about instance variables? After all most methods are going to work with some kind of data which has to be stored somewhere. Modules can include attribute accessor definitions. As far as actual instance variables go, recall that instance variables are only created when they are assigned to, so there are no variable definitions as such. The methods and modules can contain code which sets or gets instance variables. When these methods are called they will create instance variables in the object they are called on. There is however an issue with potential name clashes if methods in two different modules happen to use a variable with the same name. So you have to be careful when naming variables.

  67. Summary This is the end of module 6. In this module you've learned about the remainder of the Ruby language features. You've become familiar with the details of defining and using blocks. You've seen how blocks can be converted into objects with the help of procs and lambdas. You found out about constants and the fact that they aren't so constant. Finally you've learned about modules which are Ruby's way of organizing code into namespaces or packaging common functionality into reusable chunks and mixin into class.

  68. Putting Ruby to Work Overview Hi this is Alex Korban, in this module I will talk about some of the tools and techniques you will need to develop software in Ruby. There is a lot more to using the program and language than just learning the features of the language. In order to write maintainable, readable, and bug-free code you need to become familiar with the tools and techniques relevant to the language. This is the focus of this final module. I will talk about organizing the source code across files and directories. Almost any software you create will make use of third party libraries. I will explain Ruby's approach to managing third party code and show you how you can discover and install libraries created by other developers. These libraries are called gems in the Ruby ecosystem. The Ruby community places a strong emphasis on testing software. I will introduce you to some of the test and frameworks available for you to test your code. Even with tests in place you're likely to encounter some stubborn bugs which will require you to break out the debugger. So I will demonstrate how to use the debugger built into RubyMine. Once all the kinks are ironed out and your software is ready, you'll need to package and deploy it. I will discuss some approaches you can use for that. Finally I'll provide you with references to some of the resources you will need as a Ruby developer.

  69. Organizing Source Code So far I've been working with single files containing independent programs. As Ruby doesn't enforce any particular code organization in relation to files and directories, a single file can contain a mix of classes, modules, methods, and the code that uses them. However, this is obviously not a practical way to maintain anything larger than a small script. There are two aspects to organizing code, one is the structure of the code expressed by methods, classes, and modules. The other is the structure expressed through files and directories. These two aspects typically overlap and they establish convention for organizing file hierarchies and Ruby reflects that. If you have a module and class hierarchy like this then it's typical to organize the files like this. The directories are colored in blue, let me explain what each directory is for. The idea here is to separate application code from the library code. By library code I mean the modules and classes, by application code I mean the stuff that makes use of these modules and classes. It's a good idea to make this distinction as it facilitates reuse and helps with testing. The bin directory contains executable utilities, this is typically used for libraries which come with some executables. So if you are creating an application you may not have anything in there. If you need to include documentation with your software the conventional location is the doc folder. The library code goes into the lib directory. As it's separated out it's easy to include it in multiple different application files and it's easy to write a test run which is going to exercise this code in place of the actual application. Let's take a look at the contents of the lib directory. Each module gets a corresponding directory on the lib, I have a module called deep_space, so it's got a corresponding folder. Note the difference in the naming convention. Class and module names uses camelCase, but corresponding file names should use snake_case. Typically each class in that module goes into a separate file in that directory. This structure makes it easy to find the source for a class based on its fully qualified name. So in my case I need to put the spaceship class into spaceship.rb and the probe class goes into probe.rb. Deep_space.rb, located directly under the lib folder, is provided for convenience. It should include all the other necessary files so that all I need to do an application code is include deep_space.rb. Finally the test folder contains the tests. There is one more file here init.rb. This is the file that contains the main application code, it will include deep_space.rb and then kick-off the application logic. Now that the source is spread over multiple files naturally you need the ability to assemble it back into a single program to be executed. There are two mechanisms available for that. A method called require can include a file using an absolute path. When using require this way you might find it useful to refer to the current files directory. It's available in a variable called __dir__. For example, to include the spaceship class from deep_space.rb you might write this. If you don't provide an absolute path Ruby will look for the file in its load paths which is a set of predefined paths. You can examine the load paths by looking at the global variable called LOAD_PATH. Several paths are setup by default to allow you to include the standard libraries without specifying absolute paths. If you need to include additional load paths you can provide them to the Ruby interpreter using the dash I command line switch. Another thing to note is that you don't need to include the .rb extension when passing the name to require. Ruby has a second method for including files which is called require_relative. This method includes files relative to the current files directory. This method is convenient when you're including files from your own project. Both require and require_relative will not include the file again if it's already included.

  70. Gems and Managing Dependencies At some point you're going to need to do something which isn't covered by the standard libraries. So you'll need to install third party libraries. In Ruby terminology libraries are called gems. To install and manage them you use the gem command which is part of the Ruby Gems framework. This framework is installed alongside Ruby. There is a large number of open-source Ruby libraries available. They're all available from a central location rubygems.org. This is the location used by the gem command. You can also open rubygems.org in your browser and explore the available gems. This site is useful if you already know the name of the gem you're interested in, but what if you want to find out whether there is a gem available for a specific task? A very helpful tool for this is rubytoolbox.com. This site categorizes a large number of Ruby gems and also estimates their popularity. Some of the categories include Dependency Management, Email Sending, Image Processing, a lot of the categories are specific to Ruby on Rails, which is a web development framework written in Ruby, but there are also a lot of categories which are relevant to straight Ruby development. For example, if you're looking for a login library you can check the login category on Ruby Toolbox. log4r appears to be the most popular library in this category, so let's install it. Ruby actually provides a logger in extended library which is also a viable option, but for the sake of this discussion I will use log4r. If you know the name or a portion of a name of a gem you can search for it using the gem command. I can see that there is indeed a gem called log4r available and its current version is 1.1.10. To install a gem you run the gem install command. The great thing about Ruby gems is that if the gem you installed depends on other gems they will be installed to. If you're on Linux or MacOS and you're using RVM, which is the Ruby Version Manager, then you need to be aware of RVM concept of gem sets. Along with different versions of Ruby, RVM can also maintain different sets of installed gems. This is useful, for example, if you have different projects using different versions of the same gems which could potentially conflict. The gem sets allow you to compartmentalize these different versions and avoid clashes. You can specify a Ruby version and a gem set to use for your project. When you're on gem install and you have RVM, it will install the gem into the current gem set. Once a gem is installed you can run gem list to see a list of the gems that you have. I can see in this list that I have log4r installed now. The command to uninstall a gem is predictably gem uninstall followed by the gem name. To start using the gem often you just need to add a require statement with the gems name to your project. Gems are installed to allocation included in Ruby's default load paths, so you don't need to supply a path to require. If you are working on a project together with other developers then you'll need an easy way to manage your projects dependencies. Simply giving people a list of gems to install isn't going to work very well especially because gems often depend on other gems and their versions may change during the project. This is where a tool called bundler is very useful. It allows you to specify all the immediate gem dependencies and it allows you to install them along with their dependencies with a single command. Bundler is itself a gem, so you can install it by running gem install bundler. Your gem dependency spec needs to be in a file called gemfile which looks something like this. The purpose of the gemfile is to list the dependencies possibly along with sources where they can be installed from and with version requirements. After you write the gemfile you can execute bundle install and bundler will install all the required dependencies. After that it's a matter of checking in your dependency list into source control and getting every developer to install bundler and run bundle install after they check out the source. Bundler has other commands to update your gems when the gem file changes and to pull down the gem files into your project tree so that your project is less dependent on external sources and has the exact required versions of the libraries that it needs.

  71. Testing Frameworks As I mentioned earlier the Ruby community considers writing tests to be very important. Two popular approaches to developing Ruby software are called test driven development or TDD for short and behavior driven development or BDD. With both of these approaches the idea is that you write the tests first and then write the code to make the tests pass. For TDD there are a couple of unit test frameworks included in the Ruby standard libraries. One is called minitest and the other one is a wrapper around minitest which provides some additional functionality. Let me show you a couple of tests using the minitest framework. I've got a test project set up in RubyMine, depending on the versoin of the Ruby interpreter you installed, RubyMine might require you to install an additional gem called minitest reporters. Let's have a look at the structure of this test file. The first thing I need to do is require minitest/autorun. After that I include the code that I'm going to test using require_relative and I also include the module so that I don't need to prefix all the class names with module 7. The tests need to be defined as methods in a class derived from minitest, unit test case. I can perform the setup, which is shared across test methods and in the setup method. Here I create an instance of spaceship, as this is what I'm going to use in every test. Test_name and test_probes are my two tests. Test_name tests that the ships name is set correctly when it's instantiated. Test_probes tests that probes can be added to the probes array in the ship instance. As I require minitest/autorun this is all the code that I need to write. Minitest will insert a bit of code to run the tests automatically when I execute this script, even though I haven't instantiated the tests spaceship class explicitly. When I run this program, the output tells me that there are two assertions and no errors. If I change one of the asserts to be run and rerun this, then I get an error report. RubyMine also allows you to run an individual test. Here I can see that there was one assertion and no errors. So it only ran the test_probes method. These test reports are pretty basic, but for other frameworks RubyMine can provide fancier output. The minitest framework includes a lot of other assertions other than assert and assert_equal, which I used so far. For example, I can test whether an object is an instance of particular class using assert_instance_of. I can also test whether a particular block of code raises any exceptions. There are many other assertions available. Additionally minitest provides negative assertions which start with refute instead of assert. Like for example refute_equal or refult_nil. In addition to letting you write these traditional unit tests, minitest also includes the ability to write spec style tests. The spec approach puts emphasis on making tests more readable so they resemble a spec in addition to testing the code. Let me show you an example. Functionally this is quite similar, I still require mintest/autorun and then in include the code that I'm going to test. However instead of creating a test class I simply write describe Spaceship and put the test code in the block passed to it. Describe is simply a method that takes a block. The before method is like the setup method you've seen before, it allows you to perform the setup steps which are shared between individual tests. Finally the nested described calls contain actual test code. Instead of assertions spec style tests employ what's called matches. Must_equal is an example of a matcher and not that I can call it as a method on a string in this case. Minitest includes many other matches such as must_raise or must_be_nil. You can see the complete list in the library documentation. Another popular test in framework is called RSpec. It's a much more fully featured implementation of the spec based approach to testing I've just showed you with minitest. To install RSpec you just need to run gem install rspec. RSpec specs look quite similar to minitest specs you can find out more at rspec.info. Yet another popular test in framework is called cucumber. The aim of this framework is to provide the foundation for behavior driven development. You can install it by running gem install cucumber. It takes the concept of readable tests to another level with the idea that instead of tests you can have a human readable spec which also happens to be executable. With cucumber, you describe features with a series of test scenarios. A test scenario can look like this. Each line in this scenario is called a step and you can attach Ruby code to each of the steps. For example, the step where you launch probes can have this code associated with it. The match done between scenarios and test code is done using regular expressions. The contents of the capture groups in the regular expression and the step definition are passed to the code block. The code block then launches the appropriate number of probes. When you pass a file with your test scenarios to cucumber it passes the file, locates the relevant test code for each step, and executes it. You can find out more about cucumber at cukes.info. In practice cucumber is often combined with RSpec or minitest. While cucumber works well for integration and other high level testing, unit tests still have their place.

  72. Debugging Tools Testing will help you avoid the majority of the bugs, but sometimes tricky bugs will still sneak in and you'll need to figure out what caused them and fix it. Because it's so easy to covert objects to strings in Ruby and output them, _____ can be a very effective debugging tool. However you can also debug Ruby code using an interactive debugger. I'll show you how this works in RubyMine. When you try to use the debug mode in RubyMine for the first time, it might prompt you to install additional software and gems. For example, on Windows you'll need to install the Ruby def kit to be able to install debug related gems which contain native code. Please follow the instructions given by RubyMine. Once that's configured you can start debugging. I'm going to put a breakpoint in the battening hatches method of my Spaceship class. Instead of simply running the script, I need to choose the Debug mode. And when I do that RubyMine stops execution at my breakpoint. Now I can examine the state of my program, it's shown in the bottom pane. On the bottom left you can see the current call stack. The middle pane shows the variables. Self currently refers to my Spaceship instance. I've also got hatches, which is a local variable currently set to nil and I've got a list of global variables. On the right-hand side I can add watches for variables or expressions. For example I'll add the watch for the first element of the hatches array. From this point I can either continue running the program or I can execute it line by line. RubyMine allows me to step over lines or to step into to see the details of what gets executed on each line. I'm going to step over the line that initializes the hatches array. By the way, if you hover the cursor over our variable in the editor you'll get a popup where you can examine its value. You can also drill down if it has references to other objects. The bottom pane also has a tab which shows the console output of the program. I can step into the execution of each and I'm going to see each line printed out. RubyMine also provides several options to control how breakpoints are triggered and what happens when they are. I can edit a breakpoint and choose more and there are quite a few options here. You can set a condition for triggering the breakpoint, you can log a message to the console, you can disable a breakpoint until another breakpoint is hit. Additionally, you can set breakpoints to trigger when an exception is raised. If debugging an id isn't to your liking, the standard Ruby library includes debug.rb which allows you to debug a script from the command line. To run the script under the control of debug.rb you just need to load the library. You get the debugger prompt where you can enter commands to control the execution of the script. For example, next one executes one line of code stepping over method calls. You can examine the variable using p. Q quits the debugger. There are quite a few other commands, for example you can set breakpoints. You can read about the available commands in the library documentation. I will tell you where to find it at the end of the module.

  73. Packaging and Distributing Code When your application is bug free and ready to be used you'll need a way to distribute it for production use. There are several approaches you can take depending on how your application will be used. The simplest situation is if the application runs under your control, say on a server, in that case you can make sure Ruby is installed on the server, check out the source from the source control, and either install the necessary gems manually or if you use bundler run bundle install to get the dependencies. Another possibility is that you know your users have Ruby installed and they need to be able to install your software. In this case you can package your application as a gem and make it available for download. Gems are a way of packaging Ruby code and affiliated files, such as executables. They can be used to package both libraries and applications, the process is similar in both cases. Creating a gem is fairly straightforward, in fact RubyMine can help you out by creating an empty gem project. When you create a new project in RubyMine you can set the project type to Gem application and then you just need to set a name for it and you're good to go. Press OK and RubyMine will create the project structure for you. RubyMine expects you to use bundlers so make sure you install it beforehand. You can see here that RubyMine creates a project structure consistent of a number of files and directories. It follows the structure I described at the start of the module. There is a bin directory as well as lib and test. The project also has a gem file. This gem file is setup for a library and it tells bundler that dependencies are specified in the gem spec file. This is fine when your gem is a library, however if you're trying to pick a gem application you do need to specify the dependencies in the gem file not in the gem spec. Let's take a look at the gem spec file. This file contains the metadata for your gem in the form of Ruby code. There are some obvious attributes like the authors name and an email and the description of the gem. The file also contains some more interesting attributes, like the files attribute. This attribute is supposed to contain an array of file names included in your gem. By default RubyMine adds a bit of code to extract the file names from the output of git ls-files. If you are using something else for source control then of course this isn't going to work. Feel free to specify this array in some other way. Executables and test_files attributes are set using elements from the files attributes which match a given pattern. So for example, for executables it's going to look for elements from files which have been in the name. You can change these as well. You don't need to touch the require_paths attribute as long as all the files that will be required by external code are in the lib directory. The last two lines specify gems which are only used for development purposes. Development dependencies are not installed by default when the gem is installed. I'm also going to set the minimum required Ruby version. (typing) Finally I need to provide some content for the description field (typing) and for the summary. (typing) Now that I've got my gem spec defined I can build my gem. I'm in my gems directory and this is where I need to run the gem build command to build the gem. This command requires the name of the gem spec file. This command produces .gemfile. I can now use this file to install my library or application. I can do it using the gem install command. And giving it the name of the gem file. I can check that it's installed by running gem list. And I can see that this gem is now in the list of my installed gems. Now that you have a gem file you can distribute it to your users so they can install it using the gem install command. As an alternative Ruby has a built in gem distribution mechanism you can use. If you're on gem server it will start the server on port 8808 by default. Other people can access this server to install the gems which are installed on the machine which is running the server. In my case they will be able to install my test_gem using a command like this. (typing) All I need to use a gem server other than rubygems.org is specify a different URL via the source switch. So this allows you to distribute your code to people who have Ruby installed and can run commands like gem install. This may not always be an acceptable option however. If you are targeting Windows for example, you might want to provide an executable which people can simply download and run. There are some gems which will help you package your project into a single executable or platform specific package, containing both your code and the Ruby interpreter. Once such gem is called OCRA. Once you've installed it using gem install OCRA you can run a command to create an executable. To show you how this works I'm going to package a script called runner.rb which I have in my project. It uses the log4r gem we installed previously to output a string to the console. I've also got a simple gem file which lists a dependency on gem 4r. So I'm going to run a command using the OCRA executable installed with the OCRA gem and this command tells OCRA to package my script along with the dependencies it finds in the gem file. I've also told it to include all the core Ruby libraries. Runner.exe produces by OCRA is a stand-alone executable which can be run without installing Ruby. Let me just run it and I can see that it produces a line of output.

  74. Resources To finish off this module I'd like to mention a few useful resources. rubydoc.info has become a central location for Ruby documentation. It provides documentation for the core classes including Ruby such as hash. And you have to go to the Stdlib section core and in this list I can find documentation for things like Hash or String or the regular expression Class, but there's also a whole lot of other documentation available on this website. It also includes a reference for other standard library classes, such as minitest. This is where you can find the information on assertions and matches included with minitests. You can also find information about debug.rb on this website including the commands you can use to drive the debugger. What's even more convenient is that it gives you access to documentation for Ruby gems. For example you can find the documentation for log4r in here. It even provides documentation for get help projects. It can get a lot of information about creating gems at rubygems.org. Another useful resource is the Ruby language website. It has links to interpret the downloads, alternative Ruby implementations, and some useful documentation. And of course there are other websites I've already mentioned in this module, such as ruby-toolbox, rspec.info, and cukes.info.

  75. Summary This is the end of the module and the end of the Ruby Fundamentals course. In this module you've learned a few things about developing Rails software with Ruby. You've seen how you can organize your code. You found out where you can look for third party libraries. You've been introduced to some testing and debugging tools. You've also learned how to package and distribute your Ruby libraries and applications. Good-luck and I hope that you'll enjoy programming in Ruby.