DEV Community

Cover image for Learn how to create a Ruby executable
Jesse vB
Jesse vB

Posted on • Edited on

Learn how to create a Ruby executable

Don't like reading? Watch the video here.

If you have Ruby installed on your computer, we know that you can execute .rb files with the ruby <file name>.rb command. This is not what we are talking about in this article.

This article is about executing ruby programs without typing ruby, ./, or an .rb extension and being able to execute the command from anywhere in your file system.

Just like when you type gem, rails, or irb, and your console immediately recognizes and runs a program, we want to do this with our own custom-built Ruby file.

Writing the program

Create a new directory anywhere. Name it favorite_color. This new Ruby program is going to do one thing, tell us our favorite color.

Make two sub-directories inside favorite_color. Name them lib, and bin. The lib directory will house the logic of the program. The bin directory will house the executable file that requires and calls the program in lib.

By the way, 'lib' stands for 'library', and 'bin' stands for 'binaries' (executable files). You could also name the bin folder 'exe' for 'executables. Housing your program source code in lib and your executable in bin or exe is standard for Ruby gem packages.

Name the lib file favorite_color.rb, and name the bin file fav-color.rb. (We will eventually remove the .rb extension.)

~ mkdir -p favorite_color/{lib,bin} && touch favorite_color/lib/favorite_color.rb favorite_color/bin/fav-color.rb
Enter fullscreen mode Exit fullscreen mode

Your file tree should look like this:

favorite_color
├── bin
│   └── fav-color.rb
└── lib
    └── favorite_color.rb

2 directories, 2 files
Enter fullscreen mode Exit fullscreen mode

Now, add some logic to favorite_color.rb. Here's what my class will look like. Write this however you want.

  1 class FavoriteColor
  2   def initialize color
  3     @color = color
  4   end
  5
  6   def declaration
  7     "Your favorite color is #{@color}"
  8   end
  9
 10   def declare
 11     puts declaration
 12   end
 13 end
Enter fullscreen mode Exit fullscreen mode

The executable file inside the bin directory is responsible for loading the FavoriteColor class, initializing it, and calling it.

  1 require_relative "../lib/favorite_color.rb"
  2
  3 favorite_color = FavoriteColor.new("teal") #insert your real favorite color.
  4
  5 favorite_color.declare
Enter fullscreen mode Exit fullscreen mode

At this point, if you cd into bin you can execute the fav-color.rb file like you normally would and it should print the output to your console.

ruby fav-color.rb
Your favorite color is teal
Enter fullscreen mode Exit fullscreen mode

At this point, we could implement functionality in fav-color.rb to read an argument passed in which sets the color of the class, but for now we only want to focus on making this file a true executable.

Adding the shebang

A shebang refers to the characters #!. It's the prefix used when referencing the path to the interpreter that the shell should use to execute a script from the terminal. For instance, if you look at some of the executables in your /bin directories that are written in shell scripts, you will see #!/bin/sh at the top, or something similar. For Ruby scripts, you should reference /usr/bin/env. Why is that? Because the env command here is going to search for the first ruby interpreter in your PATH. The full line will look like this.

#!/usr/bin/env ruby
Enter fullscreen mode Exit fullscreen mode

You might be able to just add #! ruby or #!/usr/bin/ruby, but the safest way is to do the full reference so that the executable will work on the maximum amount of machines.

At this point, your fav-color.rb file should look something like this.

  1 #!/usr/bin/env ruby
  2
  3 require_relative "../lib/favorite_color.rb"
  4
  5 favorite_color = FavoriteColor.new("red")
  6
  7 favorite_color.declare
Enter fullscreen mode Exit fullscreen mode

Now, go ahead and try to execute the file. (Hint: at this point, with the shebang line, it is a true executable). You can still use the ruby command, but in order to take advantage of the shebang you need to type ./<file-name>. Did it work?

Most likely not. You probably don't have permission to execute the file. Each file on your machine has permissions set for reading ('r'), writing ('w'), and executing ('x'). When you first create a file, it defaults to allow you as the creator to read and write to it, and others to read it. In order to see those permissions, you need to use the shell commands ls -l, the -l flag standing for long format. If you use ZSH, you can simply type the shortcut to this which is ll. You should see something like this.

total 8
-rw-r--r--  1 jvon1904  staff   132B Oct 30 20:47 fav-color
Enter fullscreen mode Exit fullscreen mode

The total 8 refers to the total size of the directory in kilobytes.

On the second line, first column, you see -rw-r--r--.

Although cryptic at first, this is a very simple designation for the file permissions.

The first character is either - meaning it's a file. It could also be d for directory.

The next three characters are permissions for the owner, which in this case are read and write.

The fourth character is the slot for execute, x. If the owner could execute the file, it would be -rwx-r--r--.

The 5th-7th characters are for the group, which on my computer is called 'staff', and the 8th-10th characters are for others.

Changing the permissions for the file

In order to change the permissions, you need to use the chmod command.

The most straightforward way to add user permissions is to type chmod followed by a letter representing who is receiving the permission (u, the user/owner, g, the group, o others, or a all) followed by a + or - (adding/removing permissions) followed by the permission (r, w, or x) and finally the file name.

For us it would look like this.

chmod u+x fav-color
ls -l
total 8
-rwxr--r--  1 jvon1904  staff  132 Oct 30 21:00 fav-color
Enter fullscreen mode Exit fullscreen mode

There happens to be another fantastic way to set all permissions for all people with only three numbers! For instance, if you want all people to have all permissions, you would type chmod 777 <file-name>.

If you type 000 you will remove all permissions completely. Can you figure out why?

The three numbers represent the three entities being permitted (u, g, and o).

0 -> no permissions

1 -> execute permission

2 -> write permission

4 -> read permission

Then add up those numbers for any combination of the three. So a 7 means all three permissions because 7 = 1 + 2 + 4. Cool right?!

In our case, you could type chmod 744 fav-color.rb and nothing should change.

Now that we've changed the permissions, try executing the file like ./fav-color.rb and it should work!

Adding the executable to your path

At this point, we should go ahead and take off the .rb extension because it's not needed now that we've added our shebang directive and turned the file into an executable.

mv fav-color.rb fav-color
Enter fullscreen mode Exit fullscreen mode

The problem now is that you must reference the entire path of the file in order to execute it.

If you are inside the directory that contains fav-color you must type ./ before hand.

If you are inside the favorite_color root directory, you must execute it as bin/fav-color. This is not ideal. We want to be able to type fav-color from anywhere.

There are two ways to accomplish this.

  1. Exporting the full path to the executable to your $PATH variable, or

  2. Adding a link to the executable to one of your /bin directories already loaded into the $PATH.

If you are familiar with adding to your PATH, feel free to use the first option (adding export PATH=$PATH:path/to/favorite_color/bin to .zshrc, .zprofile or .bash_profile, etc.)

The recommended option in this case is to make the executable a binary in one of your bin directories.

You've probably noticed that when you venture underneath your HOME ~ directory, there are more than one 'bin' folder.

In order to not confound system critical binaries, you should place a custom binary in /usr/local/bin. We can do this by linking the file to that directory.

sudo ln -s ~/favorite_colors/bin/fav-color /usr/local/bin
Enter fullscreen mode Exit fullscreen mode

When using the ln (link) command, make sure to reference both the executable and the bin directory as abosolute paths.

You can cd into /usr/local/bin to make sure it's there.

I have a line like this.

lrwxr-xr-x  1 root  wheel    44B Oct 30 22:26 fav-color -> /Users/jvon1904/favorite_color/bin/fav-color
Enter fullscreen mode Exit fullscreen mode

It appears that linking the file to /usr/local/bin automatically allows everyone to execute it.

Give it a shot. Execute the file from anywhere in your file system simply as fav-color.

Top comments (3)

Collapse
 
alireza4130 profile image
Alireza

This is not a exectuable bro!

Executable means to execute it without installing ruby

ruby is the presquite here

Collapse
 
jvon1904 profile image
Jesse vB

That's good to hear. Thanks @miguelargentina!

Collapse
 
miguelargentina profile image
Miguel Ricardo Gomez

Thanks! Great explanation of every step, really useful!