In a Rakefile, how do you define a task with a description and prerequisites, and what do rake -T and the default task do?
answer
- a Rakefile is plain Ruby
- task name: %w[prereqs] do ... end
- each prerequisite runs once per run
- -T lists only described tasks
- bare rake runs :default
basics
~20 sA Rakefile is Ruby: task release: %w[build tag] do ... end runs its prerequisites first, each at most once per run. desc describes the next task, rake -T lists only described tasks, and a bare rake runs the task named default.
solid answer
~40 s`task :build do ... end` defines a task; `task release: %w[build tag]` adds prerequisites, which Rake invokes in order before the task's own actions, and each task runs **at most once per `rake` run** even if several tasks depend on it. `desc "Build the gem"` attaches a description to the next task defined. `rake -T` (`--tasks`) lists only tasks that have a description, showing the first sentence; `-D` prints the full text, `-AT` includes undescribed tasks, `-P` shows prerequisites and `-W` shows where each task is defined. Running `rake` with no task name runs the task named `default` (`task default: :build`); if none exists it fails with "Don't know how to build task 'default'". Rake finds the `Rakefile` by searching upward from the current directory and also loads `rakelib/*.rake`.
code
ruby · 22 lines# Rakefile
require_relative "lib/ledger_kit/version"
GEM_FILE = "pkg/ledger_kit-#{LedgerKit::VERSION}.gem"
desc "Build the gem into pkg/"
task :build do
mkdir_p "pkg"
sh "gem", "build", "ledger_kit.gemspec", "-o", GEM_FILE
end
desc "Tag the release in git"
task tag: :build do
sh "git", "tag", "v#{LedgerKit::VERSION}"
end
desc "Build, tag and push the gem"
task release: %w[build tag] do
sh "gem", "push", GEM_FILE
end
task default: :buildgo deeper
Write a task with desc and prerequisites, list tasks with rake -T, and set a default task.
Explain once-per-run invocation, why -T hides undescribed tasks, how repeated declarations merge, and when to use -P, -W and --dry-run.
Design task graphs so shared steps run once, keep helper tasks undescribed, and make failures stop the run through sh.
Decide which chores belong in Rake versus CI configuration or scripts, so local and pipeline runs share one entry point.
## A Rakefile is just Ruby Rake is Ruby's build and task runner, shipped with Ruby as a bundled gem. Its input file, the **`Rakefile`** (also `rakefile`, `Rakefile.rb` or `rakefile.rb`), has no special format: it is Ruby code that calls methods from Rake's DSL. The `rake` command looks for it in the current directory and then in parent directories, and runs tasks from the directory where it was found. Extra task files named `*.rake` in a top-level `rakelib/` directory are imported automatically. ## Defining tasks The central method is **`task`**: - `task :build do ... end` — a task named `build` with one action (the block). - `task tag: :build` or `task release: %w[build tag]` — the hash syntax lists **prerequisites**. It really is a Ruby hash: key is the task name, value the prerequisites. - `task :release do |t| ... end` — the block receives the task object, so `t.name` is available. A task may be declared several times; each declaration **adds** prerequisites and actions to the same task rather than replacing it. Inside actions you get Rake's file helpers such as `sh`, `mkdir_p`, `cp` and `rm_r`; `sh` raises and stops the run when the command exits non-zero. Use `do ... end` for task blocks, not braces: with the parenthesis-free Rakefile style, `{ }` binds to the last method call in the prerequisites expression instead of to `task`. ## How prerequisites run When you run `rake release`: 1. Rake invokes each prerequisite in order: first `build`, then `tag`. 2. `tag` has its own prerequisite `build`, which has **already run** in this process, so it is skipped. 3. Finally `release`'s own actions run. That once-per-run rule is what makes a dependency graph safe: shared prerequisites such as `build` run exactly once. A cycle (`a` needs `b`, `b` needs `a`) fails with "Circular dependency detected". ## Describing and listing tasks **`desc "..."`** applies to the **next** task defined. The listing commands read it: | Command | Shows | |---|---| | `rake -T` / `--tasks` | tasks **with** a description, first sentence only, plus argument names | | `rake -T release` | the same, filtered by a pattern | | `rake -AT` | every task, including undescribed ones | | `rake -D` / `--describe` | full descriptions | | `rake -P` / `--prereqs` | every task and its prerequisites | | `rake -W` / `--where` | the file and line where each task is defined | A task without `desc` still runs; it is just hidden from `-T`. That is often deliberate for internal helper tasks. ## The default task `rake` with no task name runs the task called **`default`**. It is an ordinary task, usually one with only prerequisites: - `task default: :build` — `rake` builds the gem. - `task default: %w[test build]` — `rake` runs the checks and then builds. If no `default` task exists, a bare `rake` fails with `Don't know how to build task 'default'` and suggests `rake --tasks`. ## Useful flags while developing - `rake -n release` (`--dry-run`) traces what would be invoked and executed without running actions. - `rake --trace release` prints every invoke and execute step and full backtraces. - `rake -f other.rake` uses a different Rakefile.
- If both tag and release depend on build, how many times does build run during rake release?Once. Rake marks a task as invoked the first time it runs in a process, and later invocations in the same run return immediately. `release` invokes `build`, then `tag` asks for `build` again and gets a no-op, so the gem is built a single time.
- Why does a task you just added not appear in rake -T?`rake -T` lists only tasks that have a description. Put `desc "..."` on the line before the `task` call, or use `rake -AT` (or `-P`) to see undescribed tasks too. The task itself runs either way.
- What happens if you declare task :build twice in the same Rakefile?Both declarations apply to the same task: their prerequisites and actions are appended, and the actions run in the order they were defined. To replace a task rather than extend it, clear it first with `Rake::Task[:build].clear`.
saying these in an interview costs you the question
- Rake runs a shared prerequisite once for each task that depends on it.
- rake -T lists every task, whether or not it has a desc.
- A Rakefile uses its own syntax, not Ruby.
- Declaring task :build a second time replaces the first definition.
- A bare rake with no default task silently does nothing.