oops_a_rake 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6122dbeca5b52f5299d5213a706c658ce6c1e3943fc7affb1e5c3f78c0157d4d
4
+ data.tar.gz: bffe2ce604a67dbcbecf2f41890737e754944765a70248c1aa9340df54fa179f
5
+ SHA512:
6
+ metadata.gz: 58b3a32e770b27fc4c5d5022ea853075a05ec6ab14ea23cecf86574d65b1b740772fac8adf076d7718f39916a640e93b78bdafbb046ae17c29e93c9837f5ea50
7
+ data.tar.gz: 6042433cb2eacbefa096f8a9197172e2fb3bd3e77bf7bebd98889639cf370ae3a7d2a2b1575f5f1a4aaf9a858af1f4508dd17fc81ecc85d8aaaa753eef712760
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ spec/examples.txt
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in oops_a_rake.gemspec
4
+ gemspec
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ oops_a_rake (0.1.0)
5
+ activesupport (>= 5.2)
6
+ rake (>= 12.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (6.0.3.4)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 0.7, < 2)
14
+ minitest (~> 5.1)
15
+ tzinfo (~> 1.1)
16
+ zeitwerk (~> 2.2, >= 2.2.2)
17
+ coderay (1.1.3)
18
+ concurrent-ruby (1.1.7)
19
+ diff-lcs (1.4.4)
20
+ i18n (1.8.5)
21
+ concurrent-ruby (~> 1.0)
22
+ method_source (1.0.0)
23
+ minitest (5.14.2)
24
+ pry (0.13.1)
25
+ coderay (~> 1.1)
26
+ method_source (~> 1.0)
27
+ rake (13.0.1)
28
+ rspec (3.10.0)
29
+ rspec-core (~> 3.10.0)
30
+ rspec-expectations (~> 3.10.0)
31
+ rspec-mocks (~> 3.10.0)
32
+ rspec-core (3.10.0)
33
+ rspec-support (~> 3.10.0)
34
+ rspec-expectations (3.10.0)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.10.0)
37
+ rspec-mocks (3.10.0)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.10.0)
40
+ rspec-support (3.10.0)
41
+ thread_safe (0.3.6)
42
+ tzinfo (1.2.7)
43
+ thread_safe (~> 0.1)
44
+ zeitwerk (2.4.1)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ oops_a_rake!
51
+ pry
52
+ rspec
53
+
54
+ BUNDLED WITH
55
+ 2.1.4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Oliver Peate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,177 @@
1
+ # OOP(s) a Rake
2
+
3
+ Write your Rake tasks as plain-old Ruby objects.
4
+
5
+ ## Setup
6
+
7
+ Add the gem to your Gemfile and `bundle install`:
8
+
9
+ ```ruby
10
+ gem "oops_a_rake"
11
+ ```
12
+
13
+ In your Rakefile, require `oops_a_rake` and require your tasks:
14
+
15
+ ```ruby
16
+ # Rakefile
17
+
18
+ require "oops_a_rake"
19
+
20
+ Dir.glob("lib/tasks/*.rb").each { |task| require_relative(task) }
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### Simple task with a description
26
+
27
+ Write a class which:
28
+
29
+ - responds to `#call`
30
+ - includes `OopsARake::Task`
31
+
32
+ ```ruby
33
+ class GreetingTask
34
+ include OopsARake::Task
35
+
36
+ description "An enthusiastic greeting"
37
+
38
+ def call
39
+ puts "Hello!"
40
+ end
41
+ end
42
+ ```
43
+
44
+ When you list all the Rake tasks in the project:
45
+
46
+ ```sh
47
+ $ bundle exec rake --tasks
48
+ ```
49
+
50
+ You should see the `greeting` task listed (note the optional 'task' suffix from
51
+ the class name is omitted):
52
+
53
+ ```
54
+ rake greeting # An enthusiastic greeting
55
+ ```
56
+
57
+ N.B. Unless you include a `description` for a task then Rake won't list it by
58
+ default. Run `bundle exec rake --tasks --all` to see tasks without descriptions.
59
+
60
+ ### Task with arguments
61
+
62
+ **Note:** Only positional arguments are supported.
63
+
64
+ ```ruby
65
+ class PersonalizedGreetingTask
66
+ include OopsARake::Task
67
+
68
+ def call(name)
69
+ puts "Hello #{name}!"
70
+ end
71
+ end
72
+ ```
73
+
74
+ Invocation:
75
+
76
+ ```sh
77
+ bundle exec rake "personalized_greeting[Bob]"
78
+ # => Hello Bob!
79
+ ```
80
+
81
+ ### Task with prequisites
82
+
83
+ ```ruby
84
+ class ComplexSetupTask
85
+ include OopsARake::Task
86
+
87
+ prerequisites :task_one, :task_two
88
+
89
+ def call
90
+ # Your implementation
91
+ end
92
+ end
93
+ ```
94
+
95
+ ### Namespaced task
96
+
97
+ ```ruby
98
+ class Admin::SpecialTask
99
+ include OopsARake::Task
100
+
101
+ def call
102
+ # Your implementation
103
+ end
104
+ end
105
+ ```
106
+
107
+ Invocation:
108
+
109
+ ```sh
110
+ bundle exec rake admin:special
111
+ ```
112
+
113
+ ## Motivation
114
+
115
+ Rake is an omnipresent tool in the Ruby world. It has some drawbacks – the main
116
+ issue I've heard repeatedly is how difficult it is to test Rake tasks.
117
+
118
+ Testing Rake tasks isn't impossible, but it's complex and requires some
119
+ familiarity with how Rake works (see [Test Rake Tasks Like a BOSS][testing-tasks]
120
+ for an excellent guide).
121
+
122
+ As a result I've seen many codebases which opt for writing thin Rake tasks that
123
+ call a plain Ruby object, which is tested in isolation:
124
+
125
+ ```ruby
126
+ task :greeting do |_, args|
127
+ GreetingTask.new(*args).call
128
+ end
129
+ ```
130
+
131
+ Instead of writing this glue-code by hand it's cleaner to write your tasks as
132
+ objects:
133
+
134
+ ```ruby
135
+ # lib/tasks/greeting_task.rb
136
+
137
+ class GreetingTask
138
+ include OopsARake::Task
139
+
140
+ def call(name)
141
+ puts "Hello #{name}"
142
+ end
143
+ end
144
+ ```
145
+
146
+ To test this task you can then initialize a new instance and invoke `#call`.
147
+ This side-steps any requirement to manage Rake's world in tests. For example in
148
+ RSpec:
149
+
150
+
151
+ ```ruby
152
+ require "tasks/greeting_task"
153
+
154
+ RSpec.describe GreetingTask do
155
+ it "personalizes the greeting" do
156
+ task = described_class.new
157
+ task.call("Bob")
158
+
159
+ # ... rest of your test
160
+ end
161
+ end
162
+ ```
163
+
164
+ This approach is heavily inspired by Sidekiq, which allows jobs to be tested the
165
+ same way:
166
+
167
+ ```ruby
168
+ class HardWorker
169
+ include Sidekiq::Worker
170
+
171
+ def perform(name, count)
172
+ # do something
173
+ end
174
+ end
175
+ ```
176
+
177
+ [testing-tasks]: https://thoughtbot.com/blog/test-rake-tasks-like-a-boss
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: [:spec]
@@ -0,0 +1,6 @@
1
+ require "oops_a_rake/task"
2
+ require "oops_a_rake/version"
3
+
4
+ module OopsARake
5
+ class Error < StandardError; end
6
+ end
@@ -0,0 +1,23 @@
1
+ require "rake"
2
+ require "active_support/core_ext/string"
3
+
4
+ module OopsARake
5
+ class Registry
6
+ @tasks = {}
7
+
8
+ def self.register(task_class)
9
+ task_name = task_class.name.underscore.gsub("/", ":").delete_suffix("_task")
10
+
11
+ task = Rake::Task.define_task(task_name) do |_, args|
12
+ task_class.new.call(*args)
13
+ end
14
+
15
+ @tasks[task_class] = task
16
+ task
17
+ end
18
+
19
+ def self.fetch(task_class)
20
+ @tasks.fetch(task_class)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ require_relative "registry"
2
+
3
+ module OopsARake
4
+ module Task
5
+ def self.included(klass)
6
+ Registry::register(klass)
7
+ klass.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def description(description)
12
+ task.comment = description
13
+ end
14
+
15
+ def prerequisites(*args)
16
+ task.enhance(args)
17
+ end
18
+
19
+ alias_method :prerequisite, :prerequisites
20
+
21
+ private
22
+
23
+ def task
24
+ ::OopsARake::Registry.fetch(self)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module OopsARake
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "lib/oops_a_rake/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "oops_a_rake"
5
+ spec.version = OopsARake::VERSION
6
+ spec.authors = ["Oliver Peate"]
7
+
8
+ spec.summary = "Write Rake tasks with plain Ruby objects"
9
+ spec.homepage = "https://github.com/odlp/oops_a_rake"
10
+ spec.license = "MIT"
11
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
12
+
13
+ spec.metadata["homepage_uri"] = spec.homepage
14
+ spec.metadata["source_code_uri"] = spec.homepage
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "activesupport", ">= 5.2"
25
+ spec.add_dependency "rake", ">= 12.0"
26
+
27
+ spec.add_development_dependency "pry"
28
+ spec.add_development_dependency "rspec"
29
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oops_a_rake
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Oliver Peate
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-11-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".gitignore"
76
+ - ".rspec"
77
+ - Gemfile
78
+ - Gemfile.lock
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lib/oops_a_rake.rb
83
+ - lib/oops_a_rake/registry.rb
84
+ - lib/oops_a_rake/task.rb
85
+ - lib/oops_a_rake/version.rb
86
+ - oops_a_rake.gemspec
87
+ homepage: https://github.com/odlp/oops_a_rake
88
+ licenses:
89
+ - MIT
90
+ metadata:
91
+ homepage_uri: https://github.com/odlp/oops_a_rake
92
+ source_code_uri: https://github.com/odlp/oops_a_rake
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: 2.5.0
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.0.3
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Write Rake tasks with plain Ruby objects
112
+ test_files: []