Gemwork
Gemwork is an abstract framework used by pdobb's Ruby Gems.
Support for Rails applications is also included, but not as the automatic default. See the "Rails" subheadings in the below sections.
Installation
Add this line to your my_gem.gemspec
file:
spec.add_development_dependency "gemwork"
And then execute:
bundle
# OR
bin/setup
Rake Integration
Gemwork provides a number of additional Rake tasks that can be integrated into your project.
Create file: ./rakelib/gemwork.rake
(If the rakelib
directory doesn't exist, create it at the project root.)
# frozen_string_literal: true
spec = Gem::Specification.find_by_name("gemwork")
# Load additional tasks defined by Gemwork.
Dir.glob(
Pathname.new(spec.gem_dir).
join("lib", "tasks", "{util,rubocop,reek,test}.rake")) do |task|
load(task)
end
# Redefine the default `rake` task.
Rake::Task["default"].clear
task :default do
run_tasks(%i[
test
rubocop
reek
])
end
Running rake -T
after this will reveal the additional tasks defined by Gemwork just as if they were defined within your project.
Rails
For a Rails project, you may need to conditionally run the above by returning early unless the current environment is development. Further, you may want to include other tasks, such as eslint
, prettier
, and test:system
.
# frozen_string_literal: true
return unless Rails.env.development?
spec = Gem::Specification.find_by_name("gemwork")
# Load additional tasks defined by Gemwork.
Dir.glob(
Pathname.new(spec.gem_dir).
join("lib", "tasks", "{util,rubocop,reek,eslint,prettier}.rake")) do |task|
load(task)
end
# Redefine the default `rake` task.
Rake::Task["default"].clear
task :default do
run_tasks(%i[
test
rubocop
reek
eslint
prettier
test:system
])
end
RuboCop Integration
Simple Usage
Add the following to the .rubocop.yml
file in your gem:
# .rubocop.yml
inherit_gem:
gemwork: lib/rubocop/.rubocop-gems.yml
Rails
Or, for a Rails project, add the following to the .rubocop.yml
file in your project:
# .rubocop.yml
require:
- rubocop-rake
- rubocop-minitest
- rubocop-performance
inherit_gem:
gemwork: lib/rubocop/.rubocop-rails.yml
Advanced Usage
The above (simple usage) will automatically includes all RuboCop configuration settings defined in Gemwork. You can, however, require individual cop definitions piecemeal:
# .rubocop.yml
# Load RuboCop plugins.
require:
- rubocop-rake
- rubocop-minitest
- rubocop-performance
# Load Cops configuration by Department.
inherit_gem:
gemwork:
- lib/rubocop/all_cops.yml
- lib/rubocop/gemspec.yml
- lib/rubocop/layout.yml
- lib/rubocop/lint.yml
- lib/rubocop/metrics.yml
- lib/rubocop/minitest.yml
- lib/rubocop/naming.yml
- lib/rubocop/performance.yml
- lib/rubocop/style.yml
# Override values from gemwork's lib/rubocop/all_cops.yml config.
AllCops:
TargetRubyVersion: 2.7
See also: RuboCop's Configuration Guide on Inheritance.
Rails
# .rubocop.yml
# Load RuboCop plugins.
require:
- rubocop-capybara
- rubocop-minitest
- rubocop-performance
- rubocop-rake
- rubocop-rails
# Load Cops configuration by Department.
inherit_gem:
gemwork:
- lib/rubocop/all_cops.yml
- lib/rubocop/layout.yml
- lib/rubocop/lint.yml
- lib/rubocop/metrics.yml
- lib/rubocop/minitest.yml
- lib/rubocop/naming.yml
- lib/rubocop/performance.yml
- lib/rubocop/rails.yml
- lib/rubocop/style.yml
# Override values from gemwork's lib/rubocop/all_cops.yml config.
AllCops:
TargetRubyVersion: 3.3
Exclude:
- bin/bundle
Reek
The reek gem doesn't support config files integration. But recommended starting configs have been placed in lib/reek/. One for gems and one for Rails projects.
Testing Support
The following requires may be added to ./test/test_helper.rb
to simplify test configuration. These requires support the gem dependencies mentioned in the following section.
# frozen_string_literal: true
require "gemwork/test/support/simplecov"
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require "say"
require "minitest/autorun"
require "gemwork/test/support/reporters"
require "gemwork/test/support/much_stub"
require "gemwork/test/support/spec_dsl"
# ...
Other Setup
Rails
For a Rails app, additional configuration may be desired to improve linter support.
eslint
The below fixes eslint linting errors in Rails (7+, ...) projects.
// .eslintrc.json
{
"env": {
"browser": true,
"es2021": true
},
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"overrides": [
{
"files": ["config/tailwind.config.js"],
"env": {
"node": true
},
"rules": {
"no-unused-vars": ["error", { "varsIgnorePattern": "defaultTheme" }]
}
}
]
}
prettier
General config recommendations for prettier:
# .prettierignore
vendor
// .prettierrc.json
{
"semi": false
}
Gem Dependencies
Gemwork depends on the following gems. None of these are actually used by Gemwork, itself, but are included for use by child gems. This is meant to ease dependency management for child gems as these things evolve over time.
Unit Testing
- minitest
- minitest-reporters -- Create customizable MiniTest output formats.
- much-stub -- Stubbing API for replacing method calls on objects in test runs.
- simplecov -- Code coverage for Ruby.
Linters
- reek -- Code smell detector for Ruby.
- rubocop -- A Ruby static code analyzer and formatter, based on the community Ruby style guide.
- rubocop-minitest -- Code style checking for Minitest files.
- rubocop-performance -- An extension of RuboCop focused on code performance checks.
- rubocop-rake -- A RuboCop plugin for Rake.
Documentation
- yard -- YARD is a Ruby Documentation tool. The Y stands for "Yay!".
Rails
For Rails projects, you may want to manually install additional gems as well:
Linters
- rubocop-rails -- A RuboCop extension focused on enforcing Rails best practices and coding conventions.
- rubocop-capybara -- Code style checking for Capybara files.
Development
Development of Gemwork often requires making updates to its code and then testing them in another child gem that uses Gemwork.
Even if the child gem already has the gemwork
gem installed from RubyGems, local changes to Gemwork can be compiled and installed as a local gem, which the child gem will then immediately utilize. To facilitate this, it is recommended to add this compile/local-install step to the child gem's bin/setup
executable:
# Example ./bin/setup for your child gem:
#!/usr/bin/env bash
# Recompile and install Gemwork locally.
if [ -n "$REBUILD_GEMWORK" ]; then
( cd ~/dev/gemwork && bin/setup && rake install:local )
fi
set -euo pipefail
IFS=$'\n\t'
set -vx
bundle install
# Do any other automated setup that you need to do here
With the above, you can opt in to using a locally built and installed Gemwork gem from your child gem:
REBUILD_GEMWORK=1 bin/setup
Testing
To test this gem (gemwork):
rake
Linters
rubocop
reek
npx prettier . --check
npx prettier . --write
Releases
To release a new version of Gemwork to RubyGems:
- Update the version number in
version.rb
- Update
CHANGELOG.md
- Run
bundle
to update Gemfile.lock with the latest version info - Commit the changes. e.g.
Bump to vX.Y.Z
- Run
rake release
, which will create a git tag for the version, push git commits and the created tag, and push the.gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/pdobb/gemwork. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the Gemwork project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.