Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/bd38d4f4c1de0f173260 to your computer and use it in GitHub Desktop.
Save JoshCheek/bd38d4f4c1de0f173260 to your computer and use it in GitHub Desktop.
Off the cuff lesson on Rake!

Rake Stuffs

Make a rake task and execute it:

$ cat Rakefile
task 'open' do
  puts "opening the users.html in Chrome"
end

$ rake open
opening the users.html in Chrome

Use sh to run a shell command inside a rake task.

Notice that Rake will print the shell command it is running.

task 'open' do
  sh "open -a 'Google Chrome.app' users.html"
end

Make the most common task the default

Delcare a task named :default. It has no body, so it will do nothing. This hash syntax means that it depends on the task open, which will cause it to run that task.

task default: 'open'
# ...

Run the default task:

$ rake
open -a 'Google Chrome.app' users.html

Give a task a description:

# ...
desc 'Open the users html page'
task 'open' do
  sh 'say "opening the users.html in Chrome"'
end

List available tasks

All tasks that have descriptions:

$ rake -T
rake open  # Open the users html page

All tasks:

$ rake -AT
rake default     #
rake open        # Open the users html page

Declare that one task depends on another task.

Our open task will fail if users.html hasn't been built.

desc 'Open the users html page'
task 'open' do
  sh "open -a 'Google Chrome.app' users.html"
end

So we can a hash again to say that open depends on users.html

This is the same thing we did with default, except the key is a string (Rake accepts strings and symbols), and we have a block to execute for this task.

desc 'Open the users html page'
task 'open' => 'users.html' do
  sh "open -a 'Google Chrome.app' users.html"
end

Generate a file if it doesn't exist.

Here, we use the file method instead of the task method. This will cause Rake to consider it satisfied (not need to be run), if the file exists. If the file doesn't exist, it will run our block and generate it. We can give this a description, like any other task, even though we don't.

file 'users.html' do
  sh 'ruby build_html.rb'
end

Regenerate a file if the data it was built from changes.

users.html was built from the data in users.json. So if that data ever updates, we want to rebuild it.

We can say that users.html depends on users.json like this:

file 'users.html' => 'users.json' do
  sh 'ruby build_html.rb'
end

Because users.html was declared with file, and it depends on users.json, which is a file, Rake will decide that it needs to run the block to build users.html if either:

  • users.html doesn't exist
  • users.json was modified more recently than users.html

Otherwise it will consider the task satisfied and do nothing:

# Doesn't build users.html, because it's up to date
$ rake
open -a 'Google Chrome.app' users.html

# Now edit users.json, add another user
# Now, users.json is more recent than users.html
# So it rebuilds users.html before opening it
$ rake
ruby build_html.rb
open -a 'Google Chrome.app' users.html

# Now that it's rebuilt, it's up to date
# So it just opens the file without building it again
$ rake
open -a 'Google Chrome.app' users.html
require 'json'
require 'erb'
template = <<HTML
<!DOCTYPE html>
<html>
<head><title>All Users</title></head>
<body>
<ul>
<% user_data['users'].each do |user_hash| %>
<li><%= user_hash['name'] %>, <%= user_hash['age'] %></li>
<% end %>
</ul>
</body>
</html>
HTML
json_filename = File.expand_path('users.json', __dir__)
html_filename = File.expand_path('users.html', __dir__)
user_data = JSON.parse File.read(json_filename)
html = ERB.new(template).result(binding)
File.write html_filename, html
task default: 'open'
desc 'Open the users html page'
task 'open' => 'users.html' do
sh "open -a 'Google Chrome.app' users.html"
end
file 'users.html' => 'users.json' do
sh 'ruby build_html.rb'
end
<!DOCTYPE html>
<html>
<head><title>All Users</title></head>
<body>
<ul>
<li>Josh, 32</li>
<li>Morgan, 24</li>
</ul>
</body>
</html>
{ "users":[
{"name":"Josh","age":32},
{"name":"Morgan","age":24}
]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment