Black Bytes
Share this post!

Category Archives for Programming

ruby constant

Everything You Need to Know About Ruby Constants

There is a lot more to Ruby constants that you might think…

For example, you can change the value of a constant, unlike other languages like C or Java.

Since this is such an important topic let’s explore it in detail in this article!

Defining Constants

A constant doesn’t require any special symbol or syntax to declare. You just need to make the first letter an uppercase letter.

The following are valid constants:

Notice that you can’t define constants inside a method.

You will get this cryptic error message:

So just define your constants outside methods, typically we want to have constant definitions at the top of your class so they are clearly visible.

You can then access these constants inside the class methods or outside the class using the following syntax:

We are going to talk a bit more about the scope of constants later in this post, so stay tuned for that!

Uninitialized Constant

One common error that you may get is this:

I want you to mentally translate this error to “constant not found Foo”. One important point to understand this error is that Ruby classes are constants.

They are constants because the first letter is uppercase. This matters because the most likely reason that you are seeing this error is that you forgot to require some file or gem that defines the constant.

Or maybe you just misspelled the name of the constant.

So keep an eye open for that.

Constants Can Change

Like I mentioned in the introduction, Ruby constants can change.

But you will see this warning message:

Your program will still work fine, but you want to avoid this.

There is no way to prevent a constant from changing because variables in Ruby are not containers, they are simply pointers to objects.

The best you can do is to use an immutable object.

Example:

Related article: Ruby mutability & the freeze method.

Notice that in this example you can still change what the AUTHOR constant is pointing to, the only thing freeze protects you from is from changing the object itself.

Constant Methods

There are a few methods dedicated to working with constants:

Method Description
constants Returns an array of symbols that represent the constants defined in a class
const_get Returns value for a constant. Takes a symbol or string as parameter
const_set Sets the value for a constant. Takes two parameters: constant name as a symbol & constant value
const_missing Same as method_missing but for constants
const_defined? Returns true if a given constant (as a symbol) has been defined
remove_const Removes a constant
private_constant Makes a constant private so it can’t be accessed outside the class with Class::ABC syntax

There are a few metaprogramming tricks you can do using these methods.

Example:

Also you can use a string like “Array” & get the actual class:

But be careful with that one since a user could inject code if the string is coming from params or some other form of user input.

In Rails, there is the constantize method which basically does const_get for you, but keep in mind that it doesn’t do any security checks.

Cheatsheet

cheatsheet-constant

Ruby Constant Scope

When you create a constant outside of any class, at the top-level of your code, that constant will be available anywhere.

Constants are also available in child classes.

Constants defined outside a nested module or class are also available inside the nested classes.

Module Mixing

Constants from mixed-in modules are also available:

Notice that this works when including the module, it won’t work if you are extending it.

Example:

Also when you use a method defined in the included method, it will use the constants defined in that module, even if the same constant is defined in the current class.

Module Nesting

I want to show you one more example with nested classes (same for modules).

Notice the A::B notation here, which we tried to use as a shortcut. But the problem is that class C won’t have access to FOO directly.

For that reason you want to stick to this kind of nesting:

In the first example you can still do ::A::FOO to access the constant, but if the class name changes then you will get an error.

This ::A::FOO syntax works because it tells Ruby to look in the top-level scope, where constants like Array & String are defined.

Video

Summary

You learned about Ruby constants, a type of variable which has some interesting behavior. You can change the value of a constant but it will print a warning.

You also learned that class names are constants & that you should avoid const_get with user input.

If you enjoyed this post don’t forget to share it so more people can understand how constants work.

ruby metaprogramming costs

The Hidden Costs of Metaprogramming

Metaprogramming sounds like a very fancy word, but is it any good?

It can be useful, but many people don’t realize that using metaprogramming has some costs.

Just so we are on the same page…

What is metaprogramming exactly?

I define metaprogramming as using any method that:

  • Alters the structure of your code (like define_method)
  • Runs a string as if it was part of your actual Ruby code (like instance_eval)
  • Does something as a reaction to some event (like method_missing)

So what are the costs of metaprogramming? I classify them into 3 groups:

  • Speed
  • Readability
  • Searchability

Note: You could also say that there is a fourth group: Security. The reason for that are the eval methods, which don’t make any kind of security checks on what is being passed in. You have to do that yourself.

Let’s explore each of those in more detail!

Speed

The first cost is speed because most metaprogramming methods are slower than regular methods.

Here is some benchmarking code:

The results (Ruby 2.2.4):

As you can see both metaprogramming methods (define_method & method_missing) are quite a bit slower than the normal method.

Here is something interesting I discovered…

The results above are from Ruby 2.2.4, but if you run these benchmarks on Ruby 2.3 or Ruby 2.4 it looks like these methods are getting slower!

Ruby 2.4 benchmark results:

I ran this benchmark several times to make sure it wasn’t a fluke.

But if you pay attention & look at the iterations per second (i/s) it seems like regular methods got faster since Ruby 2.3. That’s the reason method_missing looks a lot slower 🙂

Readability

Error messages can be less than helpful when using the instance_eval / class_eval methods.

Take a look at the following code:

This will result in the following error:

Notice that we are missing the file name (it says eval instead) & the correct line number. The good news is that there is a fix for this, these eval methods take two extra parameters:

  • a file name
  • a line number

Using the built-in constants __FILE__ & __LINE__ as the parameters for class_eval you will get the correct information in the error message.

Example:

Why isn’t this the default?

I don’t know, but it’s something to keep in mind if you are going to use these methods 🙂

Searchability

Metaprogramming methods make your code less searchable, less accessible (via worse documentation) & harder to debug.

If you are looking for a method definition you won’t be able to do CTRL+F (or whatever shortcut you use) to find a method defined via metaprogramming, especially if the method’s name is built at run-time.

The following example defines 3 methods using metaprogramming:

Tools that generate documentation (like Yard or RDoc) can’t find these methods & list them.

These tools use a technique called “Static Analysis” to find classes & methods. This technique can only find methods that are defined directly (using the def syntax).

Try running yard doc with the last example, you will see that the only method found is create_post_tags.

It looks like this:

yard example

There is a way to tell yard to document extra methods, using the @method tag, but that is not always practical.

Example:

Also if you are going to use a tool like grep, ack, or your editor to search for method definitions, it’s going to be harder to find metaprogramming methods than regular methods.

“I don’t think Sidekiq uses any metaprogramming at all because I find it obscures the code more than it helps 95% of the time.” – Mike Perham, Creator of Sidekiq

Conclusion

Not everything is bad about metaprogramming. It can be useful in the right situations to make your code more flexible.

Just be aware of the extra costs so you can make better decisions.

Don’t forget to share this post if you found it useful 🙂

ruby magic

There Is No Magic in Ruby

You may have heard (or even said yourself) that Rails / Ruby has too much magic…

…but where does that idea come from & what can you do to dispel that magic?

When something feels like magic it’s because there is something you don’t know, there is some information missing. It’s just like actual magic tricks, if you know the trick there is no magic.

Magic wand and hat

In software development, knowing the tricks is equivalent to having an understanding of how things really work.

Let’s See An Example!

This example is about BCrypt, a hashing algorithm used to store passwords securely. It is implemented in Ruby via the bcrypt gem.

Here’s how to use BCrypt to hash the word “testing”:

Notice how you get a different hash every time, but if you use something like MD5 (don’t!) or SHA1 you will always get the same output for a given string.

Why is BCrypt behaving in a different way?

I will explain what’s going on in a second, but first let’s look at how you compare two bcrypt hashes, one coming from the database & one from user input (like a form or something like that).

The part on the left (BCrypt::Password.new) is a BCrypt object, which takes the hash stored in the database as a parameter.

The part on the right (params[:password]) is just the plain-text password that the user is trying to log in with.

In this case we assume that a right user / password combination is being used.

So why is this evaluating to true?

Well, to understand this you need to know two things:

  1. BCrypt uses something called a “salt”, which is a random value used to increase security against pre-computed hashes. The salt is stored in the hash itself.
  2. In Ruby many things that look like syntax are just methods. This is the case for the double equals operator (==).

Knowing that, then I can tell you that BCrypt defines its own == method, which knows how to extract that “salt” value so that it can take that into account when comparing the passwords.

In other words, BCrypt#== takes the “salt” value from the stored hash, then it hashes the plain-text password (the user input) using this salt so that both hashes will be identical if the password is valid.

If you were to look at the source code it would look something like this:

Remember that super will call the same method (in this case ==) on the parent class. The parent class of BCrypt::Password is String.

Its All About Methods

One important thing to understand is that other than a few keywords & a few syntax elements (like parenthesis), its all about classes & methods.

So if you know what class you are working with (which you can check using the class method) you will always be able to know what operations (methods) are available.

But sometimes we just have a method call without an object, this often means the method is defined in the current class, but that’s not always the case.

Example:

Where is puts defined? Let’s find out:

Another thing that may be confusing is metaprogramming, because with metaprogramming you can create, modify or even remove methods during program execution. These things make the code more opaque & obscure.

You can reduce the confusion by being aware of what metaprogramming methods are available & how they work.

Summary

You learned how a deep understanding of how things work can help you dispel any “magic”, write better code & make you a better developer.

If you want to improve your Ruby skills check out my book, Ruby Deep Dive, which is designed to bridge the gap between the fundamentals & more advanced concepts 🙂

ruby graph theory

Practical Graph Theory in Ruby

This is the next installment in the “Practical Computer Science” series, where you will learn how to apply classic computer science concepts to solve real problems using Ruby.

Today we are going to talk about Graph Theory.

You may have heard about binary trees, they look like this:

binary-tree

The thing is that a binary tree is just a specialized version of a graph, so that should give you an idea of how widespread graphs are.

Let’s start with an overview of graph theory fundamentals, then we are going to see what are some practical uses & how to implement this in Ruby!

Graph Fundamentals

A graph is composed of two elements:

  • Nodes (or vertices)
  • Edges

One node represents one element in the graph, like a city or a street, in a graph representing a map. While the edges represent the connections between the nodes.

If you look at a computer science or math book you will see a graph defined by this formula: G(V, E).

Where G means Graph, V is the set of vertices & E is the set of edges.

Graphs can be directed or undirected. Meaning that you can only go one direction (directed graph) or both directions (undirected graph).

The most popular type of graph is the Directed Acyclic Graph (DAG). Acyclic means that there are no loops, there is no way to backtrack.

Uses for Graphs

Now that we have seen an overview of the fundamentals, let’s see some common uses for graphs.

Using graphs you can do things like:

  • Find the shortest (or longest) path between two locations
  • Check if two things are related to each other
  • Build a recommendation engine
  • Analyze dependencies

Another example includes finding the best route to a destination (think GPS devices).

How to Implement & Use Graphs

You could write your own graph implementation, but for this article we are going to stick to the RGL gem which already implements one for us.

To create a basic graph using RGL:

This code produces the following graph:

graph-1234

You can get a graphical representation of your graph like this:

Then copy the output of that method on a site that can process the dot language. Like this one.

Alternatively, you can install Graphviz on your machine to produce the image locally.

Now that we have a graph, we may want to traverse it to find out information about it.

There are two basic algorithms for searching your graph:

  • Breadth-First Search (BFS)
  • Depth-First Search (DFS)

In BFS you get the closest nodes first & in DFS you go as deep as possible for every node. These algorithms can be implemented using the stack data structure.

The RGL gem already implements those algorithms for you:

Look at the graph again & follow the path these algorithms did using just your eyes (or you can use a finger too if you want). That will help you get a sense of what’s going on.

Weighted Graphs

We can add more information to a graph in the form of weights to make it more useful.

Weights are given to edges, which are the paths between two nodes (also known as “vertices”). These weights represent the cost of going from one point to another.

For example, if we have a map of a country in the form of a graph & we want to reach a certain destination in the shortest time possible, the weights would represent the distance between two cities.

usa-graph

Or if we have a computer network, the weights may represent how many hops it takes to reach a certain network.

“In computer networking, a hop is one portion of the path between source and destination. Data packets pass through bridges, routers and gateways as they travel between source and destination. Each time packets are passed to the next network device, a hop occurs.” – Wikipedia

Here’s a code example for a weighted graph:

We can now search for the shortest path from one point to another. And that’s exactly the topic of the next section!

Finding The Shortest Path

A popular algorithm for finding the shortest path inside a graph is “Dijkstra’s Shortest Path” algorithm.

Given a weighted graph, we can use Dijkstra’s algorithm to solve this question:

“What’s the fastest way to get from point A to point B?”

Here is a code example, using the RGL gem:

This tells us the shortest path from New York to Houston, using the information available in the graph.

Summary

You have learned what a graph data structure is & how to use it with the RGL gem.

You have also learned about common algorithms for working with graphs, like DFS, BFS & Dijkstra’s.

Don’t forget to share this post if you found it useful so more people can enjoy it 🙂

ruby stringio

An Object That Behaves Like a File?

If you are looking for an object that behaves like an IO object (files, sockets, etc), but that you can control like a string, then StringIO is for you.

Let me show you some examples & things to watch out for!

Basic Examples

To create a StringIO object you can do this:

Then you can read from this object using methods like gets, read & each_line.

I made a handy table for you with the most useful methods:

Method Description
gets Read one line of input
read Read a specific amount of bytes (all by default)
each_line Given a block, iterate over each line
each_char Given a block, iterate over each character
<< Append data
rewind Reset the internal position pointer

Notice that StringIO has a position pointer. This pointer keeps track of how many bytes you have read, just like a file object does.

So every time you call a method like gets or read it will give you that amount of data & advance the pointer.

Even Enumerable methods like map or each_line will advance the position pointer, so keep that in mind.

You can reset the position pointer to the beginning using the rewind method:

That’s it for the basics. I’m going to show you some practical uses for StringIO, but first let me show you something else.

What About StringScanner?

Now you have seen what StringIO can do, but the Ruby Standard Library includes another string-related class.

That class is StringScanner.

It can be confusing since they have similar names & methods, but let me help you see the difference.

The main thing is this:

A StringIO object can replace another IO object (like a File or a Socket), but StringScanner is meant for doing things like parsing (making sense of some text by breaking it into a set of tokens).

These two classes still share something, besides having “String” in their name, they both use an internal position pointer.

Replacing Standard Input & Output

Let’s say you are writing a command-line application that ask user for output using the Kernel#gets method…

…if you want to test this code you are going to have to input something by hand every time.

So is automated testing out of the picture?

No, it isn’t!

This is where StringIO comes to the rescue. You can initialize a StringIO object with your test input & then replace the standard input object pointed by $stdin (this where Ruby looks for user input when you call gets).

This technique can also be used to capture output from methods like puts.

Display methods print to the default output device, known as ‘standard output’. In Ruby this is represented by an IO object which you can replace with your StringIO object.

Example:

This is more involved than the input version, because we want to make sure to restore the original STDOUT object & to rewind our StringIO so we can read the output.

Notice that most testing frameworks include a method to do this for you (assert_output for Minitest & the output matcher in RSpec), but it’s always great to know what’s going on behind the scenes 🙂

Summary

You learned about the StringIO class, which emulates a real IO object so it can act as a replacement for that kind of object.

This can be useful for testing classes that write output to the screen or require user input via the terminal.

If you know about some interesting uses for StringIO let us know in the comments & don’t forget to share this article so more people can enjoy it!

1 2 3 14