https://github.com/odlp/oops_a_rake
Write your Rake tasks as plain-old Ruby objects
https://github.com/odlp/oops_a_rake
rake
Last synced: about 1 year ago
JSON representation
Write your Rake tasks as plain-old Ruby objects
- Host: GitHub
- URL: https://github.com/odlp/oops_a_rake
- Owner: odlp
- License: mit
- Created: 2020-11-04T11:06:37.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2021-02-11T13:06:38.000Z (over 5 years ago)
- Last Synced: 2025-03-22T12:19:14.472Z (about 1 year ago)
- Topics: rake
- Language: Ruby
- Homepage:
- Size: 21.5 KB
- Stars: 7
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# OOP(s) a Rake
Write your Rake tasks as plain-old Ruby objects.
## Setup
Add the gem to your Gemfile and `bundle install`:
```ruby
gem "oops_a_rake"
```
In your Rakefile, require `oops_a_rake` and require your tasks:
```ruby
# Rakefile
require "oops_a_rake"
Dir.glob("lib/tasks/**/*.rb").each { |task| require_relative(task) }
```
## Usage
### Simple task with a description
Write a class which:
- responds to `#call`
- includes `OopsARake::Task`
```ruby
class GreetingTask
include OopsARake::Task
description "An enthusiastic greeting"
def call
puts "Hello!"
end
end
```
When you list all the Rake tasks in the project:
```sh
$ bundle exec rake --tasks
```
You should see the `greeting` task listed (note the optional 'task' suffix from
the class name is omitted):
```
rake greeting # An enthusiastic greeting
```
N.B. Unless you include a `description` for a task then Rake won't list it by
default. Run `bundle exec rake --tasks --all` to see tasks without descriptions.
### Task with arguments
**Note:** Only positional arguments are supported.
```ruby
class PersonalizedGreetingTask
include OopsARake::Task
def call(name)
puts "Hello #{name}!"
end
end
```
Invocation:
```sh
bundle exec rake "personalized_greeting[Bob]"
# => Hello Bob!
```
### Task with prequisites
```ruby
class ComplexSetupTask
include OopsARake::Task
prerequisites :task_one, :task_two
def call
# Your implementation
end
end
```
### Namespaced task
```ruby
class Admin::SpecialTask
include OopsARake::Task
def call
# Your implementation
end
end
```
Invocation:
```sh
bundle exec rake admin:special
```
### Task with a custom name
```ruby
class ObscureClassNameTask
include OopsARake::Task.with_options(name: "custom_name")
def call
puts "Hello"
end
end
```
Invocation:
```sh
bundle exec rake custom_name
```
## Motivation
Rake is an omnipresent tool in the Ruby world. It has some drawbacks – the main
issue I've heard repeatedly is how difficult it is to test Rake tasks.
Testing Rake tasks isn't impossible, but it's complex and requires some
familiarity with how Rake works (see [Test Rake Tasks Like a BOSS][testing-tasks]
for an excellent guide).
As a result I've seen many codebases which opt for writing thin Rake tasks that
call a plain Ruby object, which is tested in isolation:
```ruby
task :greeting do |_, args|
SomeObject.new(*args).call
end
```
Instead of writing this glue-code by hand it's cleaner to write your tasks as
objects:
```ruby
# lib/tasks/greeting_task.rb
class GreetingTask
include OopsARake::Task
def call(name)
puts "Hello #{name}"
end
end
```
To test this task you can then initialize a new instance and invoke `#call`.
This side-steps any requirement to manage Rake's world in tests. For example in
RSpec:
```ruby
require "tasks/greeting_task"
RSpec.describe GreetingTask do
it "personalizes the greeting" do
task = described_class.new
task.call("Bob")
# ... rest of your test
end
end
```
This approach is heavily inspired by Sidekiq, which allows jobs to be tested the
same way:
```ruby
class HardWorker
include Sidekiq::Worker
def perform(name, count)
# do something
end
end
```
[testing-tasks]: https://thoughtbot.com/blog/test-rake-tasks-like-a-boss