Image for post
Image for post

An introduction to DSLs by (re-)implementing Rake

We’re going to implement the very first draft of Rake — by Jim Weirich 🙏 himself

Mehdi Farsi
Sep 2 · 3 min read

In this article we’re going to explore the following topics:

  • what’s a DSL
  • DSL vs GPL
  • implementing the first version of Rake

I’m thrilled to share with you our latest project: Fun Facts about Ruby — Volume 1

Please feel free to spread the word and share this link! 🙏

Thank you for your time!

What’s a DSL?

A domain-specific language (DSL) is a computer language specialized to a particular application domain. The most popular DSL is probably HTML. Indeed, HTML is mainly used for building webpages.

DSL vs GPL

A general-purpose language (GPL) is a computer language designed to be applicable in the widest variety of domains. Here is a few examples of GPL: XML, UML, Ruby, PHP, Python, etc..

So, the main difference between DSLs and GPLs is the variety of application domains that can be covered by the language itself.

Now that we’re more familiar with the notions of DSL and GPL, let’s see how to implement a DSL in Ruby by taking the notorious Rake as example.

Jim Weirich

Jim Weirich was a respected contributor to the Ruby programming language community. His numerous talks gave me the curiosity to learn more about Ruby. Among his numerous contributions, he’s the co-creator of Ruby-Make (Rake).

About Rake

Rake is a build tool for automating tasks in Ruby. It provides a simple syntax to generate tasks and resolve tasks’ dependencies.

produces

$> rake third_task
before
first task
second task
third task

We want to execute the third_task task. In order to be executed, this task must resolve its dependencies which are [:first_task, :second_task]. That’s why first task and second task appear before third task. Finally, the before_task task is defined as dependency of both :first_task and :second_task. But this task is only executed once. Indeed, Rake only executes each task once for a given procedure.

This was the very first draft of rake developed by Jim Weirich.

my-rake

The goal here is to reproduce this basic behavior of Rake. That will help us to understand the main concepts behind the implementation of a DSL in Ruby.

For each argument in our argument list we need to find and invoke the task corresponding to this argument. This is the end of our program..

Each task is inserted in the TASKS hash. So now let’s populate TASKS with the content of our Rakefile

Here we define a task method that simply instantiate aTask class and store this instance in TASKS— Note that task is the unique command of our DSL. Then we load our Rakefile. At this point, each of our task commands in the Rakefile implicitly calls the task method defined in the my-rake script.

NB: feel free to have a look to Loading a file in Ruby if you’re unfamiliar with the load routine in Ruby.

Now let’s implement our Task class to complete our task method

Here the Task initializer stores the properties of our task command:

  • the task name
  • its dependencies
  • the block associated.

This is the content of TASKS after the execution of load './Rakefile'

Now let’s define Task#invoke to execute each task and resolve dependencies

The invoke method is in charge of 4 steps:

  • verifying if a task has already been invoked
  • resolving dependencies
  • execute the task
  • mark the task as already invoked

Finally, let’s run our script to see if it ensures the same behavior as the first draft of Rake

$> ruby micro_rake.rb third_task
before
first task
second task
third task

Here, we can see that our script works the same way as the first draft of Rake.

Thank you, Jim Weirich!!!

Conclusion

Building a DSL in Ruby becomes very natural as your DSL commands are simply method calls. The right way to write DSL in Ruby can be summarized as following:

  • define your DSL commands
  • store these commands in order to be in control of the execution flow
  • execute these commands in the right order

Voilà!

Thank you for taking the time to read this article!

Please feel free to 👏 and share if you find this article interesting.

RubyCademy

E-Learning platform for Ruby and Ruby on Rails

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store