First Steps
Runtime Environment
Runtime environment is an important concept. The concept of “environment” itself will be introduced later, but it’s not the same thing. Runtime environment is where and “by whom” your programs will be launched in Ruby. Let’s say a qualified chemist conducts an experiment in a test tube, a big glass jar and even his or her own bath. It can be used by any “interpreter” (program-launching program) in Windows, Mac and Linux.
When the author first started with a computer, there was only one runtime environment, because there was no choice. When the computer was switched on, a cursor and the letters “OK” came on, meaning a program could be loaded. Now computers have become more intelligent, and a newbie also has to understand how to launch a program, where to enter the program text, “with what” to launch the written program and which runtime environment is best.
In fact. it is not particularly important to us which actual program the system is launched in. These days a program written in any of the popular programming languages can be launched in three OS: Windows, MacOS and Linux. Usually no changes are required in the program itself. If there are, they are minimal.
Statistics on the use of operating systems shows that the most popular one today is Windows. So we will begin with Windows, although it is not the best choice. The reason we decided to do this is to get us as quickly as possible into the run of things, so that any starting programmer can write a required program as quickly as possible. After all, setting up the runtime environment is not usually a very simple matter for beginners, and its apparent complexity may scare off a student at the first stage.
In spite of the fact that we shall begin by launching our programs in the Windows OS, we advise strongly against using the Windows for launching programs in Ruby, However, if you like, this OS can be used for writing programs. In any case, the authors recommend installing Linux as soon as possible (the Linux Mint Cinnamon edition, as the simplest installation medium), and using it. If you use Mac, there is no need to install Linux.
Setting Up Windows (MacOS, Linux) For Your First Program
Terminal (also known as “console”, “shell”, “command line”) is a friend of any Ruby hacker. To run programs we’re going to build together, we need some sort of central console, a place from where these programs will be executed. Terminal is the name of this central console.
To be precise, Terminal isn’t hundred percent correct definition, but it’s often used among programmers. They say “run in terminal”, but if you dive deeper, we run all programs by a special kind of software called “shell”. In other words, we send our instructions to the shell, and terminal is just a visual wrapper around this shell, where you can configure fonts, colors, copy and paste from your screen and so on.
Looking ahead, it’s worth mentioning that there are numerous kinds of shells with slightly different flavors. The most popular is bash (name is an acronym for Bourne-again shell, a pun on the name of the Bourne shell that it replaces). However, authors of this book recommend using zsh with Oh My Zsh flavor (no need to install it right now). Zsh is slightly different from the standard one, but it’s much more convenient and gives you more flexibility.
But all the above is valid for MacOS and Linux. The standard shell for Windows is “ cmd.exe ”. If you click “Start”, then “Run”, and type cmd.exe
:
Run cmd.exe in Windows
You’ll see the black screen and command prompt:
Windows shell
“Prompt” ends with >
symbol, meaning the shell is expecting your input. For the future note that every shell has its own environment and runtime settings. Some programs and commands can mess up these settings, and if you found yourself struggling with weird shell behavior, consider restarting the shell. Even experienced programmers can take advantage of this advice. You can exit the shell by typing exit
or by clicking the close button.
On MacOS and Linux terminal is available by default among other programs, and you can run it by clicking on unappealing rectangular black icon, usually with >
sign. For these operating systems shell prompt often ends with $
symbol. It’s not always true, but keep in mind that if you see dollar sign somewhere in documentation or book, and command goes right after this sign, you don’t need to type the dollar sign. For example:
$ ls
For the code block above type ls
only (dir
if you’re on Windows). This command will show the list of files in current directory.
Regardless of operating system you’re using, type ruby
command in your terminal and press “Enter”. In case of MacOS and Linux you will not see any error, Ruby will start and will be silently awaiting for your input. On Windows you most probably see “Bad command or file name” error message. It just means that Ruby is not installed by default on Windows, and we need to install it first.
Let’s take a step back. Now and in the future if something is not right, google it. For example, google “ How to run Ruby program on Windows ” if you have difficulties running your Ruby program. Good question is half the battle. And to be honest, you can only learn to program if you can ask good questions: just think consistently and follow a logical pattern. If you can’t conquer the problem by yourself, ask your question on StackOverflow, but keep in mind it is the place where you can ask a very “precise questions” about something.
For running Ruby programs in Windows you will need to run Ruby Installer and follow instructions. After that ruby
command should be available in your terminal. Let’s run ruby -v
to see the version of installed Ruby (here and below commands should work on both Windows and Macs):
$ ruby -vruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin16]
If command above doesn’t work, try restarting your terminal. Let’s run ruby
again and write your first program. When you type ruby
(without -v
) in the terminal, it will be silently awaiting for your input. Just type puts 1+1
and hit Ctrl+D (sometimes you need to do it twice):
$ rubyputs 1+1 (hit Ctrl+D here)2$
So what do we see on the screen above? Command prompt $
, then we type ruby
. Ruby is silently running and awaiting for our input, we type puts 1+1
, after which we hold Ctrl
key and hit D
on our keyboard (it serves as “ End Of Input ” signal) and we have our program executed! 2
on the screen is the result.
Let’s dive a little bit deeper into what had happened above. When you typed ruby
your shell executed Ruby interpreter - a special program to read and run your own, human-language programs. So ruby
is just a program to run your programs.
Combination Ctrl+D (also denoted as ^D below) will be useful in your further software engineering career, and it just means “end of my output”, “I’m done here”, “now it’s your turn, smart computer”. Your terminal send a byte with the code 4 (you don’t need to remember that) and Ruby understands there won’t be any keystrokes anymore and now it’s a time to execute what a user has just typed.
Command puts 1+1
is your first program! Congratulations on that! Unfortunately we didn’t save it on the disk, because we typed it from our keyboard and it disappeared right after it was executed. But it’s not a big deal, your first program was only 8 bytes, and you can always type it again, if you want to.
But what exactly does puts 1+1
do? Before we answer this question, here is exercise for you. Try to run just 1+1
, without puts
. What happened? We don’t see anything on the screen. Actually, calculation has completed successfully, but result wasn’t put back. It’s possible when you give a long-running task to a computer, such as a set of complex calculations, the result will never be printed because you missed typing in puts
.
In other words, puts
just shows result on the screen. It’s a combination of words “put” and “string”. There are other, but similar commands in other computer languages to put results on the screen. For example in BASIC you need to type print
, in C programmers often use printf
(you can also do printf
in Ruby!).
But why do we keep puts
at the very beginning? In fact, we need to sum up two numbers first, and only after that we need to print result on the screen. Programmers say “method (or function) accepts parameter”. So, in other words, want to “put string”, and this string is going to be 1+1
. This is our parameter. Can you see how we just split this line into two parts?
Ruby offers alternative syntax for this line, which is little bit more illustrative:
puts(1+1)
Like in math language we calculate numbers in parentheses first, and then do the rest. The same rule applies to computer languages.
There are few basic math operators that you can use in Ruby:
+
to add numbers. For example:1 + 1
-
to subtract numbers. For example:5 - 2
/
to divide one number by another. For example:120 / 12
*
to multiply. For example:2 * 5
Exercise
Without looking to solution below, try to write a program that calculates the number of milliseconds in one day. How would you approach this problem? How many hours in one day? How many minutes in one hour? How many seconds in one minute? How many milliseconds in one second?
Here is the answer to exercise above:
$ rubyputs 60 * 60 * 24 * 1000(hit Ctrl+D here)
This is a purely math problem: multiply the number of seconds in one minute by the number of minutes in one hour. Then multiple it by 24 hours in a day. And after that by 1000 in order to get milliseconds instead of just seconds. Pretty straightforward, isn’t it?
Now let’s write a Ruby program to calculate this expression:
For the power function in Ruby you have to use **
. For example, 5 ** 3
is 5 * 5 * 5
and it equals 125
. So the Ruby program is as follows:
Ruby program to calculate math expression mentioned above:
puts 5**5 * 4**4 * 3**3 * 2**2 * 1**1
It’s hard to believe, but the result of this operation is exactly the same as in our previous example: the amount of milliseconds in a day! Both programs will produce 86400000
. There is no any explanation to this, just a fun fact. As exercise, try to run the following program and guess what is going to happen?
Try to guess what will be printed on the screen?
puts 60 * 60 * 24 * 1000 == 5**5 * 4**4 * 3**3 * 2**2 * 1**1
Hello, I’m Your REPL
With the case of 1 + 1
program from previous chapter, interpreter performs two actions: read (R) and evaluate (E). We had no “print” action (puts
in our case), so there was no any result on the screen. In other words, to see results we need to perform three actions:
- Read (R)
- Evaluate (E)
- Print (P)
It would be also nice if we could avoid running ruby
command from terminal every time, so we can execute programs in constant loop (L). It turns out this functionality is already there! REPL acronym stands for Read Evaluate Print Loop.
It’s very similar to Ruby interpreter, but accepts Enter key as the end of your program. Instead of exiting on Ctrl+D (end of input), it just starts reading the input again. REPL is pretty well-known definition, and not tied to the Ruby language infrastructure. Other languages have their REPLs too. Ruby’s REPL called irb
. You can type this command from your shell:
$ irb2.5.1 :001 >
Weird numbers at the beginning of the line is just the Ruby version (2.5.1). The same output is for ruby -v
command. 001
indicates the first string. In the future you’ll see how you can type multi-line mini-programs to REPL. Since REPL acronym already contains “Print” word in it, you don’t have to type puts
. Whatever you do, result will be printed on your screen.
Exercise
Calculate the number of seconds in a day, inside of a REPL without using puts
.
Principle of a least surprise says that to exit REPL you should type exit
. Let’s do it… And it works!
We would like to point out that authors rarely use default irb
as a REPL. There is a better alternative called Pry. It has the same functionality, but offers more flexibility and configuration (to be discussed later in this book).
Running a Program From a File
Running a program from a file isn’t too much more difficult that running it from a terminal. You just pass argument to a Ruby interpreter with a file name:
$ ruby app.rb
In the example above interpreter will read a program from a file app.rb
, and execute it the same way as it would be executed if you typed your program to Ruby and pressed Ctrl+D.
But the question is, where and how one should save this program, where to type it, which code editor you should use? Let’s answer the first “where” question, because answer implies that student is familiar with file system. But there could be some traps and pitfalls.
If you use Windows, consider installing Linux Mint Cinnamon edition 1 as soon as you can. If you’re on Mac, you don’t need to do anything special.
On Windows we will need to create a folder (or “directory”) on disk C: and name it “projects”. On Mac and Linux we’ll need to create this directory inside of home directory. After that we’ll need to switch to this directory, create a file there, and run this file.
In other words, at this point of time you need to know how to do four things:
- Create directory
- Change directory (switch to directory)
- Create a file in directory and put some text content to this file
- Run this file (we know how to do that already:
ruby app.rb
)
Here we could give you some Linux/MacOS commands and quit explaining Windows, but market has different opinion. Statistics show that at least half of our readers are using Windows. We hope you’ll follow our advice and install Linux (again, no need to install Linux if you’re on Mac), but we’ll give you brief details of each operating system, including Windows. Just keep in mind that it’s absolutely impossible to be a good Ruby hacker on Windows.
Skill of navigating the file system is crucial for any programmer. Like a librarian should know the location of every book in the library, programmer should know how to navigate the file system, how to search files, create, copy, and delete files. You should have a picture of the file system you’re working with in your head.
But in practice, it’s been found that most of the students don’t have a good understanding, and the right skill to navigate and work with a file system. We could give you a list of essential commands and ask to remember the list, but the more humane way is to actually explain, give options, details, and let you know about the tools that can help you on your way. So let’s spend some time on learning a file system, and get familiar with a file manager.
Hello, I’m Your File Manager
If you craft programs for more than 20 years, you know that there are hardly many tools from the past which are relevant today. It is one of many reasons we’re using Ruby now: the knowledge gained ten and more years ago is still relevant today, and hasn’t devalued over the time. However, besides Ruby there are some other tools that still work and quite useful.
One of these tools is a file manager. There are many flavors of file managers, the most popular one for Windows is Far Manager:
Far Manager running on Windows
Like it was mentioned before, working with a file system is crucial for any programmer, you should be confident with creating files, directories, copying, editing, removing files from your computer. File manager helps you a lot.
Most programming books do not cover this topic, giving you brief overview of essential shell commands. These authors assume you already know how to deal with files, and there is no emphasis on how to work with a file system efficiently, easy and fast. But we highly recommend installing and using file managers in your everyday work. File managers are far easier than shell commands, and it’s worth putting some time into it. At the same time learn file system the hard way, through shell commands. Sometimes we just need to get things done and move on, instead of spending time poking around with this or another shell command.
Because of that you don’t need to remember the list of shell commands given below. Eventually you will remember all of them. Moreover, these commands are for Linux/MacOS only. But some key combinations are for Windows. Good news is that there is unspoken rule, unwritten convention between authors of file managers: all of them have kind of the same commands and hot keys.
A careful reader will say “ Wait a minute! We want to get rid of Windows, but at the same time about to learn some Far Manager commands? ”
Well, it’s true, but with few caveats.
File manager is kind of ubiquitous tool. There are many flavors of file managers. Norton Commander is one of the first file managers, released in the age of DOS (Disk Operating System, outdated operating system from Microsoft released in 1981). Midnight Commander is another file manager for Linux/MacOS, and it’s quite popular today:
Midnight Commander running on Linux
There are some other flavors of file managers. However, Far Manager is so useful tool, so programmers have ported this manager to Linux and MacOS. You can find setup instructions by following the link above, but we’ll cover it here for MacOS (link for Windows users is available at the beginning at this chapter):
- Install HomeBrew if it’s not installed.
- Run the following command in your terminal (can take up to 15 minutes):
brew install yurikoles/yurikoles/far2l
- Run Far Manager from your terminal with
far2l
command. Keep in mind that after running Far Manager it will “block” your terminal window, you won’t be able to type anything until you close Far. The workaround for this is to run another terminal window, or open new terminal tab with ⌘+T combination.
Far Manager running on MacOS
You can try installing Far Manager on Linux by yourself, following instructions - which can be tricky for absolute beginners, but doable. You can also try Midnight Commander. Installation instructions are as follows:
$ sudo apt-get update$ sudo apt-get install mc
Type mc
to run Midnight Commander.
Exercise
If you’re on Windows, install Far Manager now, and plan switching to Linux Mint Cinnamon in the course of the next few weeks (don’t forget to backup your data before installing Linux!). If you’re on Mac or Linux, install Far Manager (recommended), Midnight Commander, or other file manager you like (you can google them by “best file manager for MacOS”).
Don’t be discouraged if this chapter was a little bit rough for you. Keep in mind that whatever you do, you’ll be able to run your Ruby programs in the cloud. For example, services like Repl.it offer hassle-free programming environment right in your browser (they also offer some free plans at the time of writing). It’s not a way to go if you’re looking to be a great software engineer, but it’s definitely a great backup plan! If nothing works on your computer, go the cloud and try setting things up locally later!
File System Essentials
Software engineers say that file system looks like a tree. Every branch is directory, each directory may have one or more sub-directories (other branches) or files (leaves). Directory can be empty. The top, main directory often called root directory (don’t confuse it with home directory, which is the root place for all the files for the current user).
And here is where miscommunication begins. If file system is tree-like, why is the main directory called root and not the trunk? In fact, branches always grow off the trunk. Also, when we imagine the tree, we assume that tree grows up. However, in all file managers branches (directories) grow down. You need to press Down key to move your cursor one position down the directory tree. Maybe it’s better to say that the top directory is not the root, but trunk?
Tree structure. Children’s art from one of Silicon Valley kindergartens. Curious programmer will ask “where is the root here?” The point is that the root node is located at the very top, which is unusual for the tree. Or do we talk about branches that grow up? There is some uncertainty, but don’t let that cool you off.
Regardless of how you call it, trees do have less branches at the top, and more at the bottom, which is not the case for the file system. In a file system all files and directories are usually sorted in alphabetical and ascending order. Probably there is no any other good analogy, and now we assume that file system is a tree-like, and it is sort of true.
By the way, we highly recommend to find out how to sort files in your file manager. One of the tricks here is to sort by modification date in descending order. With this sort order you’ll see recently modified files at the top. And a programmer usually works with the most recent files.
Sometimes only knowing the names of recently modified files in your work directory can give you a sense of what is going on with your project (and it’s one of the reasons why every beginner needs a file manager). Believe us, when you’ll try this sort mode, you will never look back, it’s so useful!
Sorting files by modification date in descending order in Finder (MacOS)
File System Navigation
File system navigation is just switching between directories to see what’s inside, to get the list of files, their names and other attributes. In Far Manager you can use Up, Down keys and Enter to switch into directory (we often say “to change directory”). Use Tab to switch from left to right panel and vice versa.
In bash (zsh or other type of shell) there are commands you need to type from your keyboard in terminal to change directories and get the list of files. It’s much easier to do in file managers, but you will definitely remember these shell commands over the time:
$ cd my_dir # switch to directory my_dir (or "change directory")$ cd .. # go one level up$ ls # list of files
Note: pound sign #
(or hash) indicates the comment. Everything after this sign will be ignored by your shell.
cd
command is pretty straightforward and easy to remember (C hange D irectory). But ls
(list) is a bit tricky. It turns out that there’s something else in the file system: hidden files! On Linux and MacOS file names of hidden files start with .
(dot), so they are often referred as dot-files. To show all the files, including hidden you need to type ls -a
(-a
here is parameter to ls
command and means “all”). But the most useful command is ls -lah
:
l
stands for “long format” or “long listing”. This long listing has file attributes, file owner information, size in bytes and modification date.a
tells that we want to show all files.h
is the flag to show meta information in human-readable format. For example, instead of “1000000000 bytes” we’ll see “1GB”.
Note that Far Manager also has the setting to show/hide hidden files, you can reach it by going to Options (F9), Panel Settings, Show Hidden and System Files.
By the way, h
flag is quite useful and in addition to ls
, is often used in other commands. For example, df -h
stands for “disk filesystem in human readable format” and will display statistics about free space on your hard drives and mounted volumes (like USB stick):
System information in terminal
Hit Ctrl+L in Far Manager to get the same useful system information about free and used disk space, memory, and so on. To hide this panel click Ctrl+L again:
Right panel with system information in Far Manager
Quite often you can switch on and off (toggle) different pieces of functionality by pressing the same key. For example, hit F3 to view a file in Far Manager and open built-in file viewer. To exit “view file” mode press F3 again. The same trick works in Midnight Commander.
We’ve gotten familiar with few shell commands (you don’t need to remember all of them, but may want to write down in your notepad or add a bookmark), but in file manager it’s all achievable with hotkeys. As you can see, hotkeys are much easier to remember, and result is more clear. Beginners not only able to see the contents of a file system without a need to remember ls
command and its parameters, but also can navigate file system easily with arrow keys.
Despite all the experience with shell commands, author of this book often jumps back to the file manager when necessary. This tool is also quite useful on new projects with directory structure you’re not familiar with.
Exercise
Walk around file system on your computer with file manager and look at directories and files you have. Use F3 key to toggle the file view. Use Tab to switch between left and right panel.
Some useful file manager hotkeys (also see the bottom bar on screenshot above):
F3
- toggle view file modeF4
- edit fileF5
- copy file or directory from current panel to anotherF6
- move file or directory from current panel to anotherF7
- create directoryF8
- remove file or directoryF9
- optionsTab
- switch from one panel to anotherCtrl+L
- toggle system information panel
As you can see, basic file operations are achievable with F-keys. If you’re planning to buy a new laptop, make sure your new laptop has physical F1, F3, F4… keys (for example, some newer Macs have touchbars instead of F-keys).
Shell Survival Guide
The first step for the beginners would be getting familiar with file system basics by using file manager. We could give you comprehensive shell commands crash course, but how many folks would lie on the ground sobbing after that? That’s not our goal. You don’t need to have a computer science degree before you write your first program. Our goal is to create programs with fun. But before we do that, we’ll give you a list of essential commands you don’t need to remember (make a bookmark and you’ll probably get to this page later, may be even in a year or two).
Create directory (or “make directory”) with a name one
(F7 in Far Manager):
$ mkdir one
Make a set of nested directories: directory one
will contain directory two
, and directory two
will contain directory three
(still F7 in Far Manager, flag -p
stands for “path”):
$ mkdir -p one/two/three
Print file contents in your terminal (file.txt
is a file name):
$ cat file.txt
Trick: there is alternative to cat
called bat
– “A cat with wings”, improvement over the cat
. You need to install bat, and it gives you color formatting, line numbers, and some other improvements.
Imagine that file.txt
is very large and you don’t want to have the entire file contents on the screen, but only first 10 lines. You can do it with head
:
$ head -10 file.txt
Show last 10 lines of file.txt
:
$ tail -10 file.txt
If there is a huge log file, and some program is constantly writing to this file, you may want to see the recent additions to the file, without restarting tail
command every time. You can do it with -f
(follow) flag:
$ tail -f file.txt
Press standard combination of Ctrl+C to quit from the command above.
Use mv
(move) command to rename files (F6 in Far Manager). Technically, renaming and moving a file is the same thing for a computer. The point is that file system has file allocation table and actual file contents. Allocation table contains only meta information about the file, like name, modification date, and the pointer to the actual physical location of file data.
So when you rename a file, in fact you update only file name in this table, without moving the file data. So renaming (or “moving”) takes only few milliseconds if this operation is performed on the same disk (even for very large files). However, if you move (or “rename”) the file from one disk to another, operating system will:
- Update file allocation table on both disks
- Copy the actual contents of a file
- Unlink (remove) the file from origin location.
That’s why it can take up to several minutes or even hours when file is large.
$ mv file1.txt file2.txt # rename one file to another$ mv file.txt .. # move file one level up$ mv file.txt ../.. # move file two levels up$ mv file.txt ~ # move file to home directory$ mv file.txt /Volumes/MyUSB # move file to USB flash drive (MacOS)$ mv file.txt /mnt/MyUSB # move file to USB flash drive (Linux)
Note that MyUSB
above is the name of your flash drive and can be different on your computer.
Copy file:
$ cp file1.txt file2.txt
Copy file to directory:
$ cp file1.txt my_directory
Exercise
Open up your terminal. List all files (ls -lah
). Create directory with the name my_directory
. List all files again, make sure directory exists now. Pick any file from current directory and copy this file to directory you just created. Use file manager to ensure you did the right job.
Copy file one level up:
$ cp file1.txt ..
Copy file two levels up:
$ cp file1.txt ../..
Here comes the command even some experienced programmers aren’t familiar with: copy multiple files to directory:
$ cp {file1.txt,file2.txt} my_directory
To copy multiple files in Far Manager you will need to select them first. It can be done with Insert (Ins) key. However, some laptop keyboards do not have this key. In this case use combination of “Shift+Up” or “Shift+Down” to select files on the panel. Selected files will be highlighted in yellow. When files have been selected, press F5 to open copy dialog.
If you had already installed Oh My Zsh instead of default “Bash” shell, you can click Tab any time you want to avoid typing the full file name. For example, type cp {f
and press Tab to see the list of available files you can include in your copy command. Same trick works for cp
, mv
and some other shell commands.
Find all files in current directory by name (command below will find all files with rb
extension):
$ find . -name '*.rb'
Find all files in current directory that have bla
as a part of the name:
$ find . -name '*bla*'
Find files without directories with rb
extension:
$ find . -name '*.rb' -type f
Keep this in mind
Often people do mistake and provide two hyphens --
instead of one -
to find
command. For example, parameter with two hyphens like --name
or --type f
is incorrect. You must use one hyphen with find
. However, some other Linux commands accept two hyphens. Don’t get confused!
As you can see, there are many ways of finding files in current directory. Current directory is indicated by dot right after find
command (separated by space). Directory of one level up is indicated by two dots. Directory of two levels up is indicated by ../..
(two dots, slash, two dots). Here is the short list of directory shortcuts with examples of find
command:
.
- current directory. Example (find all files withlog
extension):$ find . -name '*.log'
..
- directory of one level up. Example (find all files withlog
extension in directory of one level up):$ find .. -name '*.log'
../..
- directory of two levels up. Example:$ find ../.. -name '*.log'
~
- home directory (directory of current user). Example:$ find ~ -name '*.log'
/
- root (top level) directory. Example:$ find / -name '*.log'
Exercise
Try to find all log files in your root directory.
Far Manager has built-in dialog (which is quite friendly) for searching files. You can search files by using Alt+F7 combination. By default search file mask is *.*
(all files). You can also specify a substring you want to be present in these files.
Here is how you can search for “something” substring in all Ruby files in current directory:
$ find . -name '*.rb' -type f | xargs grep something
The first part should be already familiar to you. The part after pipe operator |
accepts lines and executes the grep
command for each line passing incoming line as parameter at the end of this command, for example grep something file1.rb
. Don’t worry if this syntax looks too complex for you at the moment. Eventually you will remember this command or another command. Searching through the files in current directory is one of essential things every programmer does many times a day.
How would you create empty file right in your terminal? There is useful touch command
:
$ touch file.txt
The command above will update date and time of a file if it already exists.
Use “ cat
” when you want to create a file and put some data in it:
$ cat > file.txt
Then type in your data, for example “ foo bar
”, and hit Ctrl+D combination on your keyboard (if it doesn’t work, try to Ctrl+D twice). “Ctrl+D” stands for “end of input” in POSIX systems, and your terminal should understand it.
Exercise
Create a text file and put your name to this file. Use ls -lah
command to make sure file has been already created. Use cat file.txt
to see the contents of the file.
Be Careful
cat > file.txt
will overwrite contents of the file without any warnings.
Add data to the end of file, the following command will not overwrite existing file. If file is not present, it will be created:
$ cat >> file.txt
Few notes about file system. You know that root directory is referred to as /
, and home directory as ~
. Home directory is the directory of current user. You can find out the name of current user by typing whoami
(“Who Am I?”) command:
$ whoamininja
Interesting fact that there is whereami
command in Ruby debugger Pry (will be described later), it shows the place where are you currently at while debugging a program.
Print working directory (current directory):
$ pwd/home/ninja
Show home directory path:
$ echo ~/home/ninja
Tilde ~
can be used as a part of path:
$ mkdir ~/tmp # Create tmp directory inside of your home directory$ cp file.txt ~/tmp # Copy file.txt to newly created directory
By the way, create ~/tmp
directory now for your temporary files. Existing directory located at /tmp
is intended for system files and gets wiped out on computer restart.
Remove file. Be careful, this command will not ask for confirmation:
$ rm file.txt
Remove entire directory:
$ rm -r my_directory
It’s worth mentioning, that -r
(recursive flag) is also used for some other shell commands. It tells that we want to perform operation recursively with this or another directory.
Don’t Do This
There are some bad jokes on programming websites, mentioning rm -rf /
command. This single command will remove everything on your computer and will make your operating system unusable in seconds. Moreover, flag -f
stands for “force”. So you won’t be asked for any confirmations.
Copy command mentioned above has alternative: scp
(SSH, “secured shell” copy). cp
command works for local files, but with scp
one can copy a file from one computer to another. For example, this command can be useful when there is a log file on the server and you want to download this log file for error investigation.
We’re done with essential shell commands and Linux ninja training. As you can see, there are numerous basic file operations you will need to remember eventually, but as a first step we highly recommend using file manager, and switching back to your terminal time to time.
Text Editors
There are plenty of text editors out there for all operating systems: MacOS, Linux, Windows, but we’ll be discussing only code editors. What’s the difference between text editors and code editors? Well, often text editors do not save the file in plain format. For example, Microsoft Word saves the file along with meta information like formatting, font settings, images, and so on. But our code should be “plain”.
In other words, what we type on keyboard should be saved to file. You are already familiar with minimalistic code editor:
$ cat > app.rbputs "Hello"
Type anything from your keyboard and press Ctrl+D (sometimes you need to press Ctrl+D twice). Everything you typed will be saved to app.rb
. Note that contents of app.rb
will be replaced in this case, and if you need to add data to the end of file, you need to use >>
instead of just >
.
Now you can see what was written to this file the following way:
$ cat app.rbputs "Hello"
You can also look at hexadecimal output, followed by raw data:
$ cat app.rb | hexdump -C00000000 70 75 74 73 20 22 48 65 6c 6c 6f 22 0a |puts "Hello".|0000000d
Similar output can be achieved via Far Manager: select the file, press F3, and then toggle hex view with F4:
Raw contents of app.rb (Far Manager view)
But dealing with raw cat
command is hard. Once you pressed Enter, there is no way to go back and make changes. You can’t use left and right arrow keys to navigate your program. And nobody is using cat
command for writing programs (except maybe for the purpose of showing your excellence on interview).
There are many convenient code editors that were designed to edit code and help a programmer. If editor is simple, it can be used for both editing text and code. Nano is one of the easiest code/text editors and installed on almost any operating system (except Windows):
$ nano app.rb
Nano editor, works right in your terminal
Footer has hints for available commands. For example, you can quit Nano by pressing Ctrl+X. There are much more advanced code editors like Vim and Emacs. Unfortunately, more advanced editors require more time to capture their functionality. You can find many “holy wars” on Internet about picking the right code editor. However, picking the right editor itself won’t help you acquiring computer language knowledge and programming skills. So it’s not very important which code editor you’ll be using.
Code editors like cat, nano, vim, emacs are all console editors. It means you run the command from your terminal and you don’t need to quit the terminal. It’s just a text on your screen. They’re quite useful when you work with remote machines. For example, you’ve logged in to the server and want to edit or view some files. You can do that without quitting the terminal.
But on your own machine you’re free to run any programs. And there are some code editors with graphic elements (like icons, different font styles, colors, and so on). Often these editors offer much more useful features (like live error checking, debugging, bookmarks) and make the life of a programmer much easier:
- VsCode, Visual Studio Code (don’t get confused with “Visual Studio”)
- RubyMine (requires subscription)
- Atom
- Sublime Text (fixed price)
RubyMine is not just a code editor, but Interactive Development Environment (IDE). Comprehensive tool for writing code with many features. Beginners can pick any of these editors. RubyMine offers great support on first steps, offering hints and tips. Other editors can be configured to offer this kind of support as well. However, we won’t be covering this topic in our book.
At the very beginning it’s worth using built-in code/text editor in your file manager. For example, you can create new file in Far Manager with Shift+F4 combination. At later steps feel free to use any code editor you like.
Also, you should be able to run your code editors from console:
$ code . # Will open VsCode for current directory$ code ~/tmp # Will open VsCode for tmp directory
But sometimes you need to integrate editor with your shell. In VsCode it’s achievable with:
- Cmd+P combination (or Ctrl+P on Linux/Windows). It will open up navigation bar.
- Type
>
in navigation bar to switch from file navigation to settings navigation. - Type
shell
and select “Install code in path” menu item.
Integrating VsCode with shell
Atom editor can be configured the similar way, and can be executed from shell with atom
command:
$ atom .
Exercise
Install text editor (VsCode if you don’t have any preference). Try to create few files, like 1.txt
, 2.txt
, 3.txt
and so on. In every file put the name of a person you know. Check your results with file manager. Delete files by using text editor UI.
Your First Program
In fact, your first program was 1+1
. But this time let’s create a file with the name app.rb
in your code editor with the following content:
Your first program
puts "I would hug you, but I’m just a text"
Save the file and run Ruby interpreter with parameter app.rb
:
$ ruby app.rbI would hug you, but I’m just a text
You can also type ruby app.rb
in your file manager, but when you press Enter, result will disappear! The subtlety is that program runs, “works off”, and quits. Control gets returned back to terminal or file manager. That’s why we do not see result on the screen when you run a program from file manager. But we can toggle the output screen (hide panels) by clicking Ctrl+O.
Congratulations! You’ve written something meaningful and saved your program to disk. Let’s improve it a little bit:
Print a text and wait for Enter key
puts "I would hug you, but I’m just a text"gets
In the program above we put a string on the screen and awaiting for the user input. Not just for any input, but for the whole string. Instruction gets
stands for “get string”, and string is not a character, it’s a sequence of characters. That’s why we can type any letters and must press Enter. Or we can press Enter without typing any letters, in this case gets
will return empty string (we’ll discuss return values later).
Run the program above and see what happens. If you run the program from file manager, result won’t “disappear”, because Ruby will be waiting for your input.
Now, let’s write a super simple program to learn a foreign language. Let’s take three random Spanish words: la pelota (ball), la puerta (door), la paz (peace). Imagine that you need to learn these words. How would you do that using a computer? One of the ways is to emulate a teacher. The computer will be the teacher and ask questions, and we will respond by spelling out the translation:
1 puts "How to translate la pelota?"2 gets3 puts "How to translate la puerta?"4 gets5 puts "How to translate la paz?"6 gets
Try to run this program and… it works! Not very convenient, but it is something. There are no any answers, but we have questions. And result is great, only by using puts
and gets
we’ve just built something useful! If you’re playing guitar, the following program is demonstration of how you can use your Ruby knowledge to teach yourself notes on a first string on fretboard:
Guitar teacher program
1 puts "Say a note on a 0 fret?" # The right answer is E2 gets3 puts "Say a note on a 1st fret?" # The right answer is F4 gets5 puts "Say a note on a 2nd fret?" # The right answer is F#6 gets7 puts "Say a note on a 3rd fret?" # G8 gets9 # ...
And so on up to 12th fret (E F F# G G# A A# B C C# D D# E).
Few notes about the listing above. As you may have already noticed, there are comments on some lines. Comments start with pound sign #
(or “hash”). You can leave as many comments as you want, including comments on the new line. Comments will not affect behavior of your program.
Exercise
Finish the program above if you understand music theory. If you don’t, create a program to learn 10 foreign words. Try to add some comments to your program so you can understand it better.
Another note is about encoding. Since our program has only characters from A to Z, there is no need to specify any encoding. However, if you want to use Chinese, Russian, etc. characters, you have two options:
- If you’re on Windows, first line of your program should be
# encoding: cp866
(“cp866” is the name of encoding). Also, the file should be saved using this encoding. - You don’t need to do anything if you’re on MacOS or Linux
In other words, you may face encoding problems on Windows. There will be other minor issues over the course of this book if you’re using Windows. There is a slim to zero chance to be a solid and productive Ruby programmer with this operating system (if you’re not using workarounds like virtual machines).
It doesn’t mean that Windows operating system sucks, not at all. The only reason is that some gem authors (gem is a small Ruby module, to be covered later in this book) do not test their code on Windows. Don’t blame them, because historically Ruby community and infrastructure evolved around free and open source tools, and Linux was the number one platform for Ruby. MacOS was the second, because it supports POSIX (Portable Operating System Interface), and all existing tools were somewhat compatible. Nobody was thinking about Windows, and to be honest Microsoft didn’t pay too much attention to open source when it all started.
So we highly recommend switching to a free operating system like Linux Mint Cinnamon or MacOS.
Exercise
If you’re running Windows, make an attempt to download and install VirtualBox (free) or VMWare Workstation (requires a license). With this software you’ll be able to run Linux inside of your Windows box. You will need to install Linux Mint Cinnamon 64-bit. Try to open up the terminal, install Midnight Commander, and write your first program in Linux. Do not expect immediate success, it might take a couple of tries the first time. If it doesn’t work, feel free to come back to this topic later. Important step here is to identify if your computer hardware supports virtualization. If not, you’ll probably need to install Linux instead of Windows (recommended) or upgrade your computer.
Variables in Ruby
A lot of stuff is going on. We hope you’re not feeling overwhelmed with information about the right way to run your Ruby program. Let’s jump to something fun.
Variables. Variable is a place inside of your computer’s memory where we can store a value. It’s like a cell in a honeycomb. You may be wondering, why do we need to store a value? Well, because we can read it later, or we can modify it later, it’s convenient.
But we are not obligated to modify the values of our variables. Sometimes we can introduce some variables to improve readability of our program. Often such variables named as constants, because we don’t modify them! That’s why in modern JavaScript programming language we have two keywords: let
to declare variable, and const
to introduce a constant, something you can’t change in the future. But it’s much easier in Ruby.
Let’s try to define (declare, create, make) a simple variable:
1 puts "Your age?"2 age = gets3 puts "Your age is"4 puts age
Program above will ask for the age. When age was provided, it will print out the age back to the screen:
Your age?20Your age is20
The number answered in the program was stored in a variable with the name age
. We could name it any way we want, for example a
. But in this case line 4 will look like puts a
. When it comes to naming variables, there are some important naming conventions out there, you can find them by typing “naming conventions for variables in Ruby” in your favorite search engine (we hope you’re using DuckDuckGo).
But Ruby and JavaScript you’ll see three common naming conventions:
- Snake case. Underscore
"_"
between words. Examples:client_age user_password user_password_expiration_date
Snake case is used in Ruby and often in databases for tables and column names.
- Camel case. Word starts with lowercase letter, words are separated by the following uppercase letter. For example:
clientAge userPassword userPasswordExpirationDate
Camel case is often used in JavaScript and statically typed languages (Golang, Java, etc.)
- Kebab case. Words are separated by hyphen. For example:
client-age user-password user-password-expiration-date
Kebab case is often used in HTML. For example:
<input type="text" name="login" data-error-highlight-color="red">
We need to remember only the first naming convention at the moment, because it’s used in Ruby: if variable has multiple words, use underscore. It should be noted that ideally variable should be named by using one word only. Two or more words is usually indicator of too broad context, but it’s out of topic for this book. Programmers agree that sometimes naming variables isn’t something easy:
There are only two hard things in Computer Science: cache invalidation and naming things.
– Phil Karlton
If you came up with variable name which is too long, don’t try to artificially lower the character count (for example, by renaming client_password_expiration_date
to cped
). At this stage, leave it as it is, and get back to your code later to see if you can do any refactoring (code improvement).
In addition to naming conventions, there are some variable naming rules that come from Ruby language itself: variables should start with letter and must contain only alphanumeric characters or underscore.
String Addition and Multiplication
Let’s look at the program from previous chapter. Can we do better?
1 puts "Your age?"2 age = gets3 puts "Your age is"4 puts age
We can replace line 3 and 4 with a single line. For example:
1 puts "Your age?"2 age = gets3 puts "Your age is" + age
Result:
Your age?30Your age is30
Something is missing, isn’t it? That’s right, the space is missing between words “is” and “30”. As you can see from example above, we can join two strings. From a purely math point of view adding up two strings is nonsense, but strings do concatenate (join) in computer memory. Run the following code in REPL or as a program:
"My name is " + "Roman" + " and my age is " + "30"
Result:
My name is Roman and my age is 30
Now try to add these two numbers, both represented as a string, try to guess what would be the answer?
"100" + "500"
Spoiler: answer is “100500”. In other words, if number is represented as a string (comes in quotes), Ruby will treat this number as a string. But if we just type 100 + 500
(without quotes), produced result will be 600
.
It turns out that you can also multiply string by a number:
"10" * 5 => "1010101010"
Result is "10"
repeated 5 times. If we leave space after 10, result will be represented in a more illustrative way:
"10 " * 5 => "10 10 10 10 10 "
As it was mentioned before, "10 "
is just a string, and we can use any string we want:
"I'm cool! " * 10 => "I'm cool! I'm cool! I'm cool! I'm cool! I'm cool! I'm cool! I'm co\ol! I'm cool! I'm cool! I'm cool! "
But in practice, developers often multiply a single character by 80 (legacy text screen width). We can multiply strings like "*"
, "="
, or "-"
by 80 to logically separate results from input. For example:
puts "Your age?"age = getsputs "=" * 80puts "Your age is " + age
Result:
Your age?30========================================================================Your age is 30