├── 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 tag. 5 | 6 | module Rack 7 | class Toolbar 8 | CONTENT_TYPE_REGEX = /text\/html|application\/xhtml\+xml/ 9 | INSERTION_METHOD = :before # alternatively :after 10 | INSERTION_POINT = "" # alternatively "" to have injection at the top of the body, or whatever else floats your boat. 11 | SNIPPET = <Welcome to rack-toolbar 13 | 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 | [![Get help on Codementor](https://cdn.codementor.io/badges/get_help_github.svg)](https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github) | 12 | | download rank | [![Total Downloads](https://img.shields.io/gem/rt/rack-toolbar.svg)](https://rubygems.org/gems/rack-toolbar) | 13 | | version | [![Gem Version](https://badge.fury.io/rb/rack-toolbar.png)](http://badge.fury.io/rb/rack-toolbar) | 14 | | dependencies | [![Dependency Status](https://gemnasium.com/pboling/rack-toolbar.png)](https://gemnasium.com/pboling/rack-toolbar) | 15 | | code quality | [![Code Climate](https://codeclimate.com/github/pboling/rack-toolbar.png)](https://codeclimate.com/github/pboling/rack-toolbar) | 16 | | inline documenation | [![Inline docs](http://inch-ci.org/github/pboling/rack-toolbar.png)](http://inch-ci.org/github/pboling/rack-toolbar) | 17 | | continuous integration | [![Build Status](https://secure.travis-ci.org/pboling/rack-toolbar.png?branch=master)](https://travis-ci.org/pboling/rack-toolbar) | 18 | | test coverage | [![Coverage Status](https://coveralls.io/repos/pboling/rack-toolbar/badge.png)](https://coveralls.io/r/pboling/rack-toolbar) | 19 | | homepage | [on Github.com][homepage] | 20 | | documentation | [on Rdoc.info][documentation] | 21 | | live chat | [![Join the chat at https://gitter.im/pboling/rack-toolbar](https://badges.gitter.im/Join%20Chat.svg)](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" 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 | --------------------------------------------------------------------------------