├── lib
├── rack-toolbar.rb
└── rack
│ ├── toolbar
│ └── version.rb
│ └── toolbar.rb
├── .travis.yml
├── .rspec
├── Gemfile
├── bin
├── setup
└── console
├── .gitignore
├── rack-toolbar.gemspec
├── spec
├── spec_helper.rb
└── rack
│ └── toolbar_spec.rb
├── README.md
└── Rakefile
/lib/rack-toolbar.rb:
--------------------------------------------------------------------------------
1 | require "rack/toolbar"
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.1.2
4 | - 2.2.1
5 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --require spec_helper
3 | --format documentation
4 |
--------------------------------------------------------------------------------
/lib/rack/toolbar/version.rb:
--------------------------------------------------------------------------------
1 | module Rack
2 | class Toolbar
3 | VERSION = "0.1.4"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in rack-toolbar.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euo pipefail
3 | IFS=$'\n\t'
4 |
5 | bundle install
6 |
7 | # Do any other automated setup that you need to do here
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle/
2 | /.yardoc
3 | /Gemfile.lock
4 | /_yardoc/
5 | /coverage/
6 | /doc/
7 | /pkg/
8 | /spec/reports/
9 | /tmp/
10 | *.bundle
11 | *.so
12 | *.o
13 | *.a
14 | mkmf.log
15 | /.idea
16 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require "bundler/setup"
4 | require "rack/toolbar"
5 |
6 | # You can add fixtures and/or initialization code here to make experimenting
7 | # with your gem easier. You can also use a different console, if you like.
8 |
9 | # (If you use this, don't forget to add pry to your Gemfile!)
10 | # require "pry"
11 | # Pry.start
12 |
13 | require "irb"
14 | IRB.start
15 |
--------------------------------------------------------------------------------
/rack-toolbar.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'rack/toolbar/version'
5 |
6 | Gem::Specification.new do |spec|
7 | spec.name = "rack-toolbar"
8 | spec.version = Rack::Toolbar::VERSION
9 | spec.authors = ["Peter Boling"]
10 | spec.email = ["peter.boling@gmail.com"]
11 |
12 | spec.summary = %q{Provides an easy way to create Rack Middleware that injects things into the response body}
13 | spec.description = %q{Provides an easy way to create Rack Middleware that injects things into the response body. Extracted from rack-insight.}
14 | spec.homepage = "https://github.com/pboling/rack-toolbar"
15 |
16 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17 | spec.bindir = "exe"
18 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19 | spec.require_paths = ["lib"]
20 |
21 | spec.add_development_dependency "bundler", "~> 1.9"
22 | spec.add_development_dependency "rake", "~> 13.0"
23 | spec.add_development_dependency "rspec", "~> 3.2"
24 | spec.add_development_dependency "rack-test", "~> 0.6"
25 | spec.add_development_dependency "pry", "~> 0.10"
26 | end
27 |
--------------------------------------------------------------------------------
/lib/rack/toolbar.rb:
--------------------------------------------------------------------------------
1 | require "rack/toolbar/version"
2 |
3 | # Subclasses must define a render method which returns the snippet of HTML that will be inserted into the response body
4 | # according to the INSERTION_METHOD and INSERTION_POINT. By default this is set before to the closing
" to have injection at the top of the body, or whatever else floats your boat.
11 | SNIPPET = <Welcome to rack-toolbar
13 |
14 | - Define render in Middleware subclass of Rack::Toolbar to return an HTML snippet.
15 | - or
16 | - Pass an HTML snippet as an argument and use Rack::Toolbar directly: Rack::Toolbar.new(snippet).
17 | - or
18 | - Redefine Rack::Toolbar::SNIPPET and ignore with the warnings.
19 |
20 | EOS
21 |
22 | def initialize(app, options = {})
23 | @app = app
24 | @options = options || {}
25 | @options[:snippet] ||= self.class::SNIPPET
26 | @options[:insertion_point] ||= self.class::INSERTION_POINT
27 | @options[:insertion_method] ||= self.class::INSERTION_METHOD
28 | end
29 |
30 | def call(env)
31 | @env = env
32 | @status, @headers, @response = @app.call(@env)
33 | [@status, @headers, self]
34 | end
35 |
36 | # Subclasses may override this method if they have alternate means of deciding which requests to modify.
37 | def okay_to_modify?
38 | return false if is_xhr?
39 | return false unless modifiable_content_type?
40 | true
41 | end
42 |
43 | def modifiable_content_type?
44 | @headers["Content-Type"] =~ self.class::CONTENT_TYPE_REGEX
45 | end
46 |
47 | def is_xhr?
48 | @headers["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"
49 | end
50 |
51 | def each(&block)
52 | if okay_to_modify?
53 | body = ""
54 | @response.each {|part| body << part }
55 | index = body.rindex(@options[:insertion_point])
56 | if index
57 | if @options[:insertion_method] != :before
58 | index += @options[:insertion_point].length
59 | end
60 | body.insert(index, render)
61 | @headers["Content-Length"] = body.bytesize.to_s
62 | @response = [body]
63 | end
64 | end
65 | @response.each(&block)
66 | end
67 |
68 | def render
69 | @options[:snippet]
70 | end
71 |
72 | end
73 | end
74 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require "rack/toolbar"
2 | require "rack/test"
3 | # require "pry"
4 |
5 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
6 | RSpec.configure do |config|
7 | # rspec-expectations config goes here. You can use an alternate
8 | # assertion/expectation library such as wrong or the stdlib/minitest
9 | # assertions if you prefer.
10 | config.expect_with :rspec do |expectations|
11 | # This option will default to `true` in RSpec 4. It makes the `description`
12 | # and `failure_message` of custom matchers include text for helper methods
13 | # defined using `chain`, e.g.:
14 | # be_bigger_than(2).and_smaller_than(4).description
15 | # # => "be bigger than 2 and smaller than 4"
16 | # ...rather than:
17 | # # => "be bigger than 2"
18 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true
19 | end
20 |
21 | # rspec-mocks config goes here. You can use an alternate test double
22 | # library (such as bogus or mocha) by changing the `mock_with` option here.
23 | config.mock_with :rspec do |mocks|
24 | # Prevents you from mocking or stubbing a method that does not exist on
25 | # a real object. This is generally recommended, and will default to
26 | # `true` in RSpec 4.
27 | mocks.verify_partial_doubles = true
28 | end
29 |
30 | config.include Rack::Test::Methods
31 |
32 | # These two settings work together to allow you to limit a spec run
33 | # to individual examples or groups you care about by tagging them with
34 | # `:focus` metadata. When nothing is tagged with `:focus`, all examples
35 | # get run.
36 | config.filter_run :focus
37 | config.run_all_when_everything_filtered = true
38 |
39 | # Limits the available syntax to the non-monkey patched syntax that is
40 | # recommended. For more details, see:
41 | # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
42 | # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
43 | # - http://myronmars.to/n g!
44 |
45 | # This setting enables warnings. It's recommended, but in some cases may
46 | # be too noisy due to issues in dependencies.
47 | config.warnings = true
48 |
49 | # Many RSpec users commonly either run the entire suite or an individual
50 | # file, and it's useful to allow more verbose output when running an
51 | # individual spec file.
52 | if config.files_to_run.one?
53 | # Use the documentation formatter for detailed output,
54 | # unless a formatter has already been configured
55 | # (e.g. via a command-line flag).
56 | config.default_formatter = 'doc'
57 | end
58 |
59 | # Print the 10 slowest examples and example groups at the
60 | # end of the spec run, to help surface which specs are running
61 | # particularly slow.
62 | config.profile_examples = 10
63 |
64 | # Run specs in random order to surface order dependencies. If you find an
65 | # order dependency and want to debug it, you can fix the order by providing
66 | # the seed, which is printed after each run.
67 | # --seed 1234
68 | config.order = :random
69 |
70 | # Seed global randomization in this process using the `--seed` CLI option.
71 | # Setting this allows you to use `--seed` to deterministically reproduce
72 | # test failures related to randomization by passing the same `--seed` value
73 | # as the one that triggered the failure.
74 | Kernel.srand config.seed
75 |
76 | end
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Rack::Toolbar
2 |
3 | Allows you to create simple Rack Middleware that will insert HTML (or whatever!) into responses at specific points.
4 |
5 | This gem was extracted from [Rack::Insight](https://github.com/pboling/rack-insight).
6 |
7 | | Project | Rack::Toolbar |
8 | |------------------------ | ----------------- |
9 | | gem name | rack-toolbar |
10 | | license | MIT |
11 | | expert support | [](https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github) |
12 | | download rank | [](https://rubygems.org/gems/rack-toolbar) |
13 | | version | [](http://badge.fury.io/rb/rack-toolbar) |
14 | | dependencies | [](https://gemnasium.com/pboling/rack-toolbar) |
15 | | code quality | [](https://codeclimate.com/github/pboling/rack-toolbar) |
16 | | inline documenation | [](http://inch-ci.org/github/pboling/rack-toolbar) |
17 | | continuous integration | [](https://travis-ci.org/pboling/rack-toolbar) |
18 | | test coverage | [](https://coveralls.io/r/pboling/rack-toolbar) |
19 | | homepage | [on Github.com][homepage] |
20 | | documentation | [on Rdoc.info][documentation] |
21 | | live chat | [](https://gitter.im/pboling/rack-toolbar?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) |
22 | | Spread ~♡ⓛⓞⓥⓔ♡~ | [on Coderbits][coderbits], [on Coderwall][coderwall] |
23 |
24 | [semver]: http://semver.org/
25 | [pvc]: http://docs.rubygems.org/read/chapter/16#page74
26 | [railsbling]: http://www.railsbling.com
27 | [peterboling]: http://www.peterboling.com
28 | [coderbits]: https://coderbits.com/pboling
29 | [coderwall]: http://coderwall.com/pboling
30 | [documentation]: http://rdoc.info/github/pboling/rack-toolbar/frames
31 | [homepage]: https://github.com/pboling/rack-toolbar
32 |
33 | *NOTE*: As it goes with all middleware that modifies the response, not compatible with Rails' streaming responses
34 | because it modifies the response.
35 |
36 | ## Installation
37 |
38 | Add this line to your application's Gemfile:
39 |
40 | ```ruby
41 | gem 'rack-toolbar'
42 | ```
43 |
44 | And then execute:
45 |
46 | $ bundle
47 |
48 | Or install it yourself as:
49 |
50 | $ gem install rack-toolbar
51 |
52 | ## Usage
53 |
54 | If your app is delivering a response like:
55 |
56 |
57 |
58 |
59 | Important
60 |
61 |
62 |
63 | ### Simple Setup
64 |
65 | You want to inject something into the response!
66 |
67 | Configure your app to use Rack::Toolbar
68 |
69 | use Rack::Toolbar, {snippet: "More Important!
", insertion_point: "", insertion_method: :after}
70 |
71 | The `div` specified will be injected `:after` the `
74 |
75 |
76 | More Important!
77 | Important
78 |
79 |
80 |
81 | ### Easy Setup
82 |
83 | You want to build a Middleware that will deliver a custom response based on whatever.
84 |
85 | Create your middleware to inherit from Rack::Toolbar, and define a `render` method:
86 |
87 | class CustomMiddleware < Rack::Toolbar
88 | def render
89 | ""
90 | end
91 | end
92 |
93 | Configure your app to use your CustomMiddleware. You can still use the `:insertion_*` options, but `:snippet` will be ignored.
94 |
95 | use CustomMiddleware, {insertion_point: "", insertion_method: :before}
96 |
97 | ## Development
98 |
99 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
100 |
101 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
102 |
103 | ## Contributing
104 |
105 | 1. Fork it ( https://github.com/[my-github-username]/destination_errors/fork )
106 | 2. Create your feature branch (`git checkout -b my-new-feature`)
107 | 3. Commit your changes (`git commit -am 'Add some feature'`)
108 | 4. Push to the branch (`git push origin my-new-feature`)
109 | 5. Make sure to add tests!
110 | 6. Create a new Pull Request
111 |
112 | ## Contributors
113 |
114 | See the [Network View](https://github.com/pboling/rack-toolbar/network)
115 |
116 | ## Alternatives
117 |
118 | Other projects which will allow you to build Middleware to inject stuff into responses:
119 |
120 | * [rack-plastic](https://github.com/techiferous/rack-plastic)
121 |
--------------------------------------------------------------------------------
/spec/rack/toolbar_spec.rb:
--------------------------------------------------------------------------------
1 | describe Rack::Toolbar do
2 |
3 | it "has a version number" do
4 | expect(Rack::Toolbar::VERSION).not_to be nil
5 | end
6 |
7 | context "request" do
8 | def app(*args)
9 | Rack::Builder.new do
10 | use Rack::Toolbar, *args
11 | run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Important
"]] }
12 | end
13 | end
14 |
15 | it "inserts into the response" do
16 | response = Rack::MockRequest.new(app).get("/")
17 | expect(response.body).to eq "Important
Welcome to rack-toolbar
\n \n - Define render in Middleware subclass of Rack::Toolbar to return an HTML snippet.
\n - or
\n - Pass an HTML snippet as an argument and use Rack::Toolbar directly: Rack::Toolbar.new(snippet).
\n - or
\n - Redefine Rack::Toolbar::SNIPPET and ignore with the warnings.
\n
\n"
18 | end
19 |
20 | def ajax_app(*args)
21 | Rack::Builder.new do
22 | use Rack::Toolbar, *args
23 | run lambda { |env| [200, {"Content-Type" => "text/html", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}, ["Important
"]] }
24 | end
25 | end
26 |
27 | it "does not modify Ajax request" do
28 | response = Rack::MockRequest.new(ajax_app).post("/")
29 | expect(response.body).to eq %[Important
]
30 | end
31 | context "via use" do
32 | it "Allows customization of snippet" do
33 | response = Rack::MockRequest.new(app({:snippet => "Custom
"})).get("/")
34 | expect(response.body).to eq "Important
Custom
"
35 | end
36 | it "Allows customization of insertion point" do
37 | response = Rack::MockRequest.new(app(:snippet => %[], :insertion_point => "")).get("/")
38 | expect(response.body).to eq %[Important
]
39 | end
40 | it "Allows customization of insertion method" do
41 | response = Rack::MockRequest.new(app(:snippet => %[], :insertion_method => :after)).get("/")
42 | expect(response.body).to eq %[Important
]
43 | end
44 | end
45 |
46 | context "via subclass" do
47 | it "Allows customization" do
48 | class SubclassOfRackToolbar < Rack::Toolbar
49 | def render
50 | "Custom Render
"
51 | end
52 | end
53 | app_using_subclass = Rack::Builder.new do
54 | use SubclassOfRackToolbar
55 | run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Important
"]] }
56 | end
57 |
58 | response = Rack::MockRequest.new(app_using_subclass).get("/")
59 | expect(response.body).to eq "Important
Custom Render
"
60 | end
61 | it "works with custom INSERTION_POINT" do
62 | class SomeClass < Rack::Toolbar
63 | INSERTION_POINT = ""
64 | def render
65 | %[]
66 | end
67 | end
68 | app_using_subclass = Rack::Builder.new do
69 | use SomeClass
70 | run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Important
"]] }
71 | end
72 |
73 | response = Rack::MockRequest.new(app_using_subclass).get("/")
74 | expect(response.body).to eq %[Important
]
75 | end
76 | it "works with custom INSERTION_METHOD" do
77 | class OtherClass < Rack::Toolbar
78 | INSERTION_METHOD = :after
79 | INSERTION_POINT = ""
80 | def render
81 | %[Injected
]
82 | end
83 | end
84 | app_using_subclass = Rack::Builder.new do
85 | use OtherClass
86 | run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Important
"]] }
87 | end
88 |
89 | response = Rack::MockRequest.new(app_using_subclass).get("/")
90 | expect(response.body).to eq %[Injected
Important
]
91 | end
92 | context "use with options" do
93 | class CustomClass < Rack::Toolbar
94 | INSERTION_METHOD = :after
95 | INSERTION_POINT = ""
96 | def render
97 | %[Injected
]
98 | end
99 | end
100 |
101 | it "Ignores customization of snippet" do
102 | app_using_subclass = Rack::Builder.new do
103 | use CustomClass, :snippet => "Custom
"
104 | run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Important
"]] }
105 | end
106 | response = Rack::MockRequest.new(app_using_subclass).get("/")
107 | expect(response.body).to eq "Injected
Important
"
108 | end
109 | it "Allows customization of insertion point" do
110 | app_using_subclass = Rack::Builder.new do
111 | use CustomClass, :insertion_point => ""
112 | run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Important
"]] }
113 | end
114 | response = Rack::MockRequest.new(app_using_subclass).get("/")
115 | expect(response.body).to eq %[Important
Injected
]
116 | end
117 | it "Allows customization of insertion method" do
118 | app_using_subclass = Rack::Builder.new do
119 | use CustomClass, :insertion_method => :before
120 | run lambda { |env| [200, {"Content-Type" => "text/html"}, ["Important
"]] }
121 | end
122 | response = Rack::MockRequest.new(app_using_subclass).get("/")
123 | expect(response.body).to eq %[Injected
Important
]
124 | end
125 | end
126 |
127 | end
128 |
129 | end
130 | end
131 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Galtzo FLOSS Rakefile v1.0.2 - 2025-08-12
4 | #
5 | # MIT License (see License.txt)
6 | #
7 | # Copyright (c) 2025 Peter H. Boling (galtzo.com)
8 | #
9 | # Expected to work in any project that uses Bundler.
10 | #
11 | # Sets up tasks for rspec, minitest, rubocop, reek, yard, and stone_checksums.
12 | #
13 | # rake build # Build my_gem-1.0.0.gem into the pkg directory
14 | # rake build:checksum # Generate SHA512 checksum of my_gem-1.0.0.gem into the checksums directory
15 | # rake build:generate_checksums # Generate both SHA256 & SHA512 checksums into the checksums directory, and git commit them
16 | # rake bundle:audit:check # Checks the Gemfile.lock for insecure dependencies
17 | # rake bundle:audit:update # Updates the bundler-audit vulnerability database
18 | # rake clean # Remove any temporary products
19 | # rake clobber # Remove any generated files
20 | # rake coverage # Run specs w/ coverage and open results in browser
21 | # rake install # Build and install my_gem-1.0.0.gem into system gems
22 | # rake install:local # Build and install my_gem-1.0.0.gem into system gems without network access
23 | # rake reek # Check for code smells
24 | # rake reek:update # Run reek and store the output into the REEK file
25 | # rake release[remote] # Create tag v1.0.0 and build and push my_gem-1.0.0.gem to rubygems.org
26 | # rake rubocop # alias rubocop task to rubocop_gradual
27 | # rake rubocop_gradual # Run RuboCop Gradual
28 | # rake rubocop_gradual:autocorrect # Run RuboCop Gradual with autocorrect (only when it's safe)
29 | # rake rubocop_gradual:autocorrect_all # Run RuboCop Gradual with autocorrect (safe and unsafe)
30 | # rake rubocop_gradual:check # Run RuboCop Gradual to check the lock file
31 | # rake rubocop_gradual:force_update # Run RuboCop Gradual to force update the lock file
32 | # rake spec # Run RSpec code examples
33 | # rake test # Run tests / run spec task with test task
34 | # rake yard # Generate YARD Documentation
35 |
36 | require "bundler/gem_tasks"
37 |
38 | defaults = []
39 |
40 | is_ci = ENV.fetch("CI", "false").casecmp("true") == 0
41 |
42 | ### DEVELOPMENT TASKS
43 | # Setup Kettle Soup Cover
44 | begin
45 | require "kettle-soup-cover"
46 |
47 | Kettle::Soup::Cover.install_tasks
48 | # NOTE: Coverage on CI is configured independent of this task.
49 | # This task is for local development, as it opens results in browser
50 | defaults << "coverage" unless Kettle::Soup::Cover::IS_CI
51 | rescue LoadError
52 | desc("(stub) coverage is unavailable")
53 | task("coverage") do
54 | warn("NOTE: kettle-soup-cover isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
55 | end
56 | end
57 |
58 | # Setup Bundle Audit
59 | begin
60 | require "bundler/audit/task"
61 |
62 | Bundler::Audit::Task.new
63 | defaults.push("bundle:audit:update", "bundle:audit")
64 | rescue LoadError
65 | desc("(stub) bundle:audit is unavailable")
66 | task("bundle:audit") do
67 | warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
68 | end
69 | desc("(stub) bundle:audit:update is unavailable")
70 | task("bundle:audit:update") do
71 | warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
72 | end
73 | end
74 |
75 | # Setup RSpec
76 | begin
77 | require "rspec/core/rake_task"
78 |
79 | RSpec::Core::RakeTask.new(:spec)
80 | # This takes the place of `coverage` task when running as CI=true
81 | defaults << "spec" if !defined?(Kettle::Soup::Cover) || Kettle::Soup::Cover::IS_CI
82 | rescue LoadError
83 | desc("spec task stub")
84 | task(:spec) do
85 | warn("NOTE: rspec isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
86 | end
87 | end
88 |
89 | # Setup MiniTest
90 | begin
91 | require "rake/testtask"
92 |
93 | Rake::TestTask.new(:test) do |t|
94 | t.test_files = FileList["tests/**/test_*.rb"]
95 | end
96 | rescue LoadError
97 | desc("test task stub")
98 | task(:test) do
99 | warn("NOTE: minitest isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
100 | end
101 | end
102 |
103 | # rubocop:disable Rake/DuplicateTask
104 | if Rake::Task.task_defined?("spec") && !Rake::Task.task_defined?("test")
105 | desc "run spec task with test task"
106 | task test: :spec
107 | elsif !Rake::Task.task_defined?("spec") && Rake::Task.task_defined?("test")
108 | desc "run test task with spec task"
109 | task spec: :test
110 | else
111 | # Add spec as pre-requisite to 'test'
112 | Rake::Task[:test].enhance(["spec"])
113 | end
114 | # rubocop:enable Rake/DuplicateTask
115 |
116 | # Setup RuboCop-LTS
117 | begin
118 | require "rubocop/lts"
119 |
120 | Rubocop::Lts.install_tasks
121 | # Make autocorrect the default rubocop task
122 | defaults << "rubocop_gradual:autocorrect"
123 | rescue LoadError
124 | desc("(stub) rubocop_gradual is unavailable")
125 | task(:rubocop_gradual) do
126 | warn("NOTE: rubocop-lts isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
127 | end
128 | end
129 |
130 | # Setup Reek
131 | begin
132 | require "reek/rake/task"
133 |
134 | Reek::Rake::Task.new do |t|
135 | t.fail_on_error = true
136 | t.verbose = false
137 | t.source_files = "{lib,spec,tests}/**/*.rb"
138 | end
139 |
140 | # Store current Reek output into REEK file
141 | require "open3"
142 | desc("Run reek and store the output into the REEK file")
143 | task("reek:update") do
144 | # Run via Bundler if available to ensure the right gem version is used
145 | cmd = [Gem.bindir ? File.join(Gem.bindir, "bundle") : "bundle", "exec", "reek"]
146 |
147 | output, status = Open3.capture2e(*cmd)
148 |
149 | File.write("REEK", output)
150 |
151 | # Mirror the failure semantics of the standard reek task
152 | unless status.success?
153 | abort("reek:update failed (reek reported smells). Output written to REEK")
154 | end
155 | end
156 | defaults << "reek:update" unless is_ci
157 | rescue LoadError
158 | desc("(stub) reek is unavailable")
159 | task(:reek) do
160 | warn("NOTE: reek isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
161 | end
162 | end
163 |
164 | # Setup Yard
165 | begin
166 | require "yard"
167 |
168 | YARD::Rake::YardocTask.new(:yard) do |t|
169 | t.files = [
170 | # Source Splats (alphabetical)
171 | "lib/**/*.rb",
172 | "-", # source and extra docs are separated by "-"
173 | # Extra Files (alphabetical)
174 | "*.cff",
175 | "*.md",
176 | "*.txt",
177 | "REEK",
178 | ]
179 | end
180 | defaults << "yard"
181 | rescue LoadError
182 | desc("(stub) yard is unavailable")
183 | task(:yard) do
184 | warn("NOTE: yard isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
185 | end
186 | end
187 |
188 | ### RELEASE TASKS
189 | # Setup stone_checksums
190 | begin
191 | require "stone_checksums"
192 |
193 | GemChecksums.install_tasks
194 | rescue LoadError
195 | desc("(stub) build:generate_checksums is unavailable")
196 | task("build:generate_checksums") do
197 | warn("NOTE: stone_checksums isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
198 | end
199 | end
200 |
201 | task default: defaults
202 |
--------------------------------------------------------------------------------