00:00:25.210
I'll go ahead and introduce myself while we're waiting. Since this is not really pertinent information, it's okay to start early. My name's Jim Weirich, and I'm with Edge Case.
00:00:30.740
I am the chief scientist at Edge Case. Now you may be aware that Edge Case was just purchased this year by Digital Raker, forming a new company called New Context. Edge Case is one of the companies in the New Context grouping of companies.
00:00:45.590
My new boss, Mike, the boss of my boss, is here. We were discussing titles, and I asked him whether I would get a new title under the new regime. He said, 'Oh yes! What would you like?' I decided that rather than chief scientist, I would like to go as chief mad scientist, but he felt that was too much of a bump up. We decided to go with the title, 'Cold Mat' instead.
00:01:11.060
So, I'm here to talk about Rake. We call this talk 'Basic Rake.' I submitted a proposal, but I realized that there was so much information to convey that it's more like a boot camp type thing. So rather than covering the whole 'basic training boot camp' concept, I’m going to just give you a bit of information about Rake and the reason I want to do this.
00:01:33.630
I've been looking at a lot of Rake files that people have been using, and oh my gosh, it is being used entirely wrong! It's a case of 'you’re doing it wrong.' How many people here are Rails developers? Right, so you use Rake. Maybe DB migrate might be the extent of what you do with it, that's okay. I'm here to tell you how to take advantage of Rake.
00:02:04.500
I'm going to give you some basic information about Rake, how it works, and how you can use it to improve your life. Rake is a tool for organizing tasks—tasks are things that you need to have done. So I'm going to start with kind of an overall concept.
00:02:27.000
Let's say I'm hungry and want to make some mac and cheese. What do I need to do to prepare this meal? First, I need to have some pasta available, some cheese, and I have to boil the water. These are some of the subtasks involved in preparing this mac and cheese meal.
00:02:52.680
There are dependencies here—in order to make mac and cheese, I need to ensure that all these things are completed first. This is the essence of Rake: taking a task and breaking it down into its component pieces while specifying what needs to be done in order to accomplish the bigger task.
00:03:35.220
If you take this metaphor and run it out with Rake, it would look something like this. I would specify my main task here as 'mac and cheese.' Every task I define will have a title, which is just Ruby code formatted in a Rake file. So our task names will be symbols; they could also be strings—Rake doesn’t care.
00:04:11.580
So, every task has a name, and every task has an action. That action is encoded within a do-end block, which gets executed to perform that task. Finally, tasks have dependencies, and we specify those dependencies using a specific syntax.
00:04:30.540
You may think it looks a bit unusual, but if you think about it, it’s just a hash syntax that uses some quirks of Ruby. When you pass a hash, it acts like an argument that gets passed into the task method. So we extract the keys, which represent the task name, and the values in the hash are the dependencies.
00:05:05.750
For example, in order to make mac and cheese, I must boil the water, buy the cheese, and buy the pasta—all three things must be done. On the command line, I would enter 'rake mac_and_cheese' to execute that task. As you would expect, the system would respond with commands like boiling water, buying pasta, buying cheese, and finally making the mac and cheese.
00:05:43.740
However, I quickly realized a problem. I started boiling the water and then ran out to the store to buy the cheese and the pasta, only to come back to find the water was still boiling—or worse, it might have boiled too long!
00:06:06.540
What I really want to specify is that before I boil the water, I need to ensure that I have both the cheese and the pasta on hand. This means I need to add these dependencies to my Rake file before boiling the water.
00:06:20.130
Once I've done that, I've not changed anything else in the Rake file, but now, magically, Rake knows to buy the pasta, buy the cheese, boil the water, and subsequently make the mac and cheese in the correct order. Getting those dependencies right is crucial in Rake.
00:06:49.960
Declare all the dependencies explicitly. If something must be done before another task, make it an explicit dependency, and Rake will ensure things are completed in the right order.
00:07:10.960
I also want to point out that each of these tasks can be individual tasks. Although I say 'rake mac_and_cheese,' I could just as easily have said 'rake buy_cheese,' and that would have executed just that individual task. You can invoke these individual tasks or the broader task that encompasses everything.
00:07:46.890
Now, let’s take this further. I realized that I may need another task called 'go to the store.' In order to buy the cheese and pasta, I need to go somewhere. In this case, we need to consider the 'go to the store' task as another dependency.
00:08:05.650
So we can define a task 'go to the store' which will have dependencies of 'buy cheese' and 'buy pasta.' If I run this task, I would automatically see a correct order of operations. Rake ensures that if 'go to the store' needs to be completed first, it will do so.
00:08:27.590
This leads us to a thought: I have two dependencies to 'go to the store.' Why wouldn’t it go to the store twice? Let’s explore how Rake handles dependencies.
00:08:58.280
When I specified 'mac_and_cheese' as my first task, Rake goes through the list of dependencies. It sees there are three dependencies that must be satisfied before making mac and cheese: boil water, buy pasta, and buy cheese. The first dependency, boiling water, in turn has its own dependencies.
00:09:36.330
So, Rake will recursively check these dependencies. If 'boil_water' depends on 'buy_pasta,' it first checks whether 'buy_pasta' has been completed.
00:09:50.820
Once it sees 'go to the store' must be done before buying the pasta or cheese, it executes that first. Rake is smart enough to recognize when tasks have already been completed, so if 'go to the store' has already been taken care of, it won’t try to do it again.
00:10:36.540
This prevents Rake from repeating the same task unnecessarily. After the dependencies have been satisfied, it can proceed to boil the water and finally make the mac and cheese.
00:10:52.630
Rake is driven by a very small codebase—around 100 lines—that efficiently walks through the tree of dependencies and executes everything in a depth-first manner.
00:11:35.600
And that's essentially the basics—the essence of Rake concerns itself with getting dependencies right and declaring them clearly. Now, what else is notable about Rake?
00:12:11.640
For convenience, Rake allows you to declare a default task. If you simply run 'rake' without specifying a task, it will attempt to execute the default task and satisfy its dependencies if you have set them. This way, you can quickly execute the main tasks as needed.
00:12:53.800
Rake will also notice circular dependencies if you define them. And it will complain until you resolve those issues. However, in real-life scenarios, such instances don't happen very often.
00:13:24.440
Now, let's discuss the environment that Rake runs in. You likely have a project directory that contains your Rake file, which is where you put all your tasks. Rake recognizes this file automatically.
00:13:56.650
You don't have to include every single task in the main Rake file. If you want to break it down into components, you can create a directory called 'Rake tasks' and place individual files with a .rake extension inside it.
00:14:35.220
Additionally, if you're running a Rails project, Rails will direct Rake to look for extra tasks in the 'lib/tasks' directory, where you can also place Rake files. This way, you can modularize your Rake tasks and make your project structure cleaner.
00:15:22.180
One important consideration when breaking tasks into separate files is the potential for tasks to conflict with each other, especially if you have the same task name in different files.
00:15:55.590
To mitigate this, Rake allows you to define tasks within a namespace. I didn't do this in the previous example with mac and cheese, but for better organization, I could define a namespace like 'apple.' Everything within that namespace will be independent of other tasks with the same name.
00:16:29.620
You can create nested namespaces as deep as you wish, allowing for modular Rake tasks that can be shared across different projects without any conflicts.
00:17:05.630
Now, Rake is primarily a command line tool, but how many people here use an IDE like RubyMine?
00:17:30.450
Using an IDE like RubyMine has ready execution for Rake tasks. However, if you're working in the command line and change directories, you might find that your Rake file is not in the current directory. Rake is smart enough to go back up the directory structure to locate its Rake file.
00:18:22.440
When you run a command from deep within your project, Rake will use the correct project directory to execute tasks, allowing you to reference files relative to that directory.
00:18:52.360
Now let's discuss some commands available within Rake. The -P command can provide you with a list of all tasks defined in your Rake files along with their dependencies.
00:19:06.030
For example, you can see that 'boil_water' depends on 'buy_pasta' and 'buy_cheese,' while 'go_to_store' depends on nothing. This command is very handy for visualizing task relationships.
00:19:55.700
Another useful command is -T. This command will only show documented tasks, so if you have comments or descriptions associated with your tasks, you need to include those for the output to reflect them.
00:20:36.670
You can also filter tasks with a string using the -T option, which will let you search through your task names. For example, if you wanted to find all tasks containing 'buy,' you could easily do that.
00:21:18.520
There is also a new command that was recently added to Rake which allows you to search for a task by name. If you input a task name, Rake will tell you in which file and on which line that task is defined. However, this only works for documented tasks.
00:22:11.010
Another powerful feature is the ability to pass environment variables directly to Rake. This is particularly useful when working within Rails. You can define an environment variable right on the command line.
00:22:54.270
This feature is convenient because it allows you to pass single-use variables that only apply to that execution of Rake. You can also set longer-lasting environmental variables.
00:23:31.540
In Rake, you can easily execute Ruby commands and some shell commands for tasks. For instance, you might run 'git status' more simply instead of a lengthy Rake command.
00:24:26.220
For more advanced use cases, Rake would allow you to build more complex automated operations— such as labor-intensive processes involving multiple files being generated dynamically.
00:25:02.880
In conclusion, Rake opens a wide range of possibilities for automating tasks in your Ruby or Rails projects. You can use it to generate, manage, and manipulate files, run commands, or structure your development process creatively.
00:25:58.420
With the range of features available in Rake, I encourage all of you to explore what it can do to improve your own workflow, and unleash the full potential of this powerful tool! Thank you for your time!