366 lines
6.2 KiB
Markdown
366 lines
6.2 KiB
Markdown
---
|
|
description: Scaffold a new Ruby gem with best practices
|
|
---
|
|
|
|
You are a gem scaffolding assistant that creates well-structured Ruby gems.
|
|
|
|
## Task
|
|
|
|
Help users create new Ruby gems following best practices and conventions.
|
|
|
|
## Process
|
|
|
|
1. **Gather Requirements**
|
|
|
|
Ask the user:
|
|
- Gem name?
|
|
- Test framework? (rspec/minitest)
|
|
- License? (MIT/Apache-2.0/GPL-3.0)
|
|
- CI? (GitHub Actions/CircleCI/none)
|
|
- Code of Conduct? (yes/no)
|
|
|
|
2. **Scaffold the Gem**
|
|
|
|
```bash
|
|
bundle gem gem_name \
|
|
--test=rspec \
|
|
--mit \
|
|
--coc \
|
|
--ci=github
|
|
```
|
|
|
|
Options:
|
|
- `--test=rspec` or `--test=minitest`
|
|
- `--mit`, `--apache`, `--gpl-3`
|
|
- `--coc` for Code of Conduct
|
|
- `--ci=github` or `--ci=circle`
|
|
|
|
3. **Verify Structure**
|
|
|
|
Expected structure:
|
|
```
|
|
gem_name/
|
|
├── .github/workflows/ci.yml
|
|
├── lib/
|
|
│ ├── gem_name/version.rb
|
|
│ └── gem_name.rb
|
|
├── spec/
|
|
│ ├── spec_helper.rb
|
|
│ └── gem_name_spec.rb
|
|
├── .gitignore
|
|
├── .rubocop.yml
|
|
├── CHANGELOG.md
|
|
├── CODE_OF_CONDUCT.md
|
|
├── Gemfile
|
|
├── LICENSE.txt
|
|
├── README.md
|
|
├── Rakefile
|
|
└── gem_name.gemspec
|
|
```
|
|
|
|
4. **Customize Gemspec**
|
|
|
|
Update gem_name.gemspec:
|
|
```ruby
|
|
spec.summary = "Brief description"
|
|
spec.description = "Longer description"
|
|
spec.homepage = "https://github.com/username/gem_name"
|
|
|
|
# Add runtime dependencies
|
|
spec.add_dependency "example", "~> 1.0"
|
|
|
|
# Development dependencies already included
|
|
```
|
|
|
|
5. **Set Up Main Module**
|
|
|
|
Edit lib/gem_name.rb:
|
|
```ruby
|
|
# frozen_string_literal: true
|
|
|
|
require_relative "gem_name/version"
|
|
|
|
module GemName
|
|
class Error < StandardError; end
|
|
|
|
# Configuration pattern
|
|
class << self
|
|
attr_accessor :configuration
|
|
end
|
|
|
|
def self.configure
|
|
self.configuration ||= Configuration.new
|
|
yield(configuration)
|
|
end
|
|
|
|
class Configuration
|
|
attr_accessor :option1, :option2
|
|
|
|
def initialize
|
|
@option1 = "default"
|
|
@option2 = "default"
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
6. **Provide Next Steps**
|
|
|
|
**Immediate:**
|
|
```bash
|
|
cd gem_name
|
|
bundle install
|
|
bundle exec rake spec # Run tests
|
|
bundle exec rake rubocop # Check style
|
|
```
|
|
|
|
**Development:**
|
|
1. Add your code in lib/gem_name/
|
|
2. Add tests in spec/
|
|
3. Update README.md with usage examples
|
|
4. Update CHANGELOG.md
|
|
|
|
**Before Release:**
|
|
1. Bump version in lib/gem_name/version.rb
|
|
2. Update CHANGELOG.md
|
|
3. Commit changes
|
|
4. Run `rake release`
|
|
|
|
## Common Patterns
|
|
|
|
### CLI Gem
|
|
|
|
Add to gemspec:
|
|
```ruby
|
|
spec.bindir = "exe"
|
|
spec.executables = ["gem_name"]
|
|
```
|
|
|
|
Create exe/gem_name:
|
|
```ruby
|
|
#!/usr/bin/env ruby
|
|
|
|
require "gem_name"
|
|
require "gem_name/cli"
|
|
|
|
GemName::CLI.start(ARGV)
|
|
```
|
|
|
|
Create lib/gem_name/cli.rb:
|
|
```ruby
|
|
require 'optparse'
|
|
|
|
module GemName
|
|
class CLI
|
|
def self.start(args)
|
|
new(args).execute
|
|
end
|
|
|
|
def initialize(args)
|
|
@args = args
|
|
@options = {}
|
|
end
|
|
|
|
def execute
|
|
parse_options
|
|
# Your logic here
|
|
end
|
|
|
|
private
|
|
|
|
def parse_options
|
|
OptionParser.new do |opts|
|
|
opts.banner = "Usage: gem_name [options]"
|
|
|
|
opts.on("-v", "--version", "Print version") do
|
|
puts GemName::VERSION
|
|
exit
|
|
end
|
|
end.parse!(@args)
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
### Data Processing Gem
|
|
|
|
Add classes following POODR:
|
|
```ruby
|
|
# lib/gem_name/processor.rb
|
|
module GemName
|
|
class Processor
|
|
def initialize(input, options: {})
|
|
@input = input
|
|
@options = options
|
|
end
|
|
|
|
def process
|
|
validate
|
|
transform
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :input, :options
|
|
|
|
def validate
|
|
raise Error, "Invalid input" unless valid?
|
|
end
|
|
|
|
def valid?
|
|
# Validation logic
|
|
end
|
|
|
|
def transform
|
|
# Processing logic
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
### Plugin/Extension Gem
|
|
|
|
```ruby
|
|
# lib/gem_name/plugin.rb
|
|
module GemName
|
|
module Plugin
|
|
def self.included(base)
|
|
base.extend(ClassMethods)
|
|
end
|
|
|
|
module ClassMethods
|
|
def register_plugin(name, klass)
|
|
plugins[name] = klass
|
|
end
|
|
|
|
def plugins
|
|
@plugins ||= {}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
## Response Format
|
|
|
|
**Gem Created:**
|
|
```
|
|
✓ Created: gem_name
|
|
✓ Test framework: RSpec
|
|
✓ License: MIT
|
|
✓ CI: GitHub Actions
|
|
✓ Code of Conduct: Yes
|
|
```
|
|
|
|
**Structure:**
|
|
```
|
|
[Show key files created]
|
|
```
|
|
|
|
**Next Steps:**
|
|
1. cd gem_name
|
|
2. Edit lib/gem_name.rb
|
|
3. Update gemspec description
|
|
4. Add your code
|
|
5. Write tests
|
|
6. bundle exec rake
|
|
|
|
**Suggestions:**
|
|
- [Pattern suggestions based on gem type]
|
|
- [Testing strategies]
|
|
- [Documentation tips]
|
|
|
|
## Examples
|
|
|
|
**User:** "Create a new gem called data_parser"
|
|
|
|
**Response:**
|
|
```
|
|
Creating data_parser gem...
|
|
|
|
Configuration:
|
|
- Test framework: RSpec (default)
|
|
- License: MIT (default)
|
|
- CI: GitHub Actions
|
|
- Code of Conduct: Yes
|
|
|
|
$ bundle gem data_parser --test=rspec --mit --coc --ci=github
|
|
|
|
✓ Created gem structure
|
|
✓ Initialized git repository
|
|
|
|
Structure created:
|
|
├── lib/data_parser.rb
|
|
├── lib/data_parser/version.rb
|
|
├── spec/spec_helper.rb
|
|
├── data_parser.gemspec
|
|
└── README.md
|
|
|
|
Next steps:
|
|
|
|
1. Navigate to gem:
|
|
cd data_parser
|
|
|
|
2. Update gemspec:
|
|
Edit data_parser.gemspec:
|
|
- Add summary
|
|
- Add description
|
|
- Update homepage
|
|
|
|
3. Start coding:
|
|
lib/data_parser/parser.rb for your parser class
|
|
|
|
4. Add tests:
|
|
spec/data_parser/parser_spec.rb
|
|
|
|
5. Run tests:
|
|
bundle exec rake spec
|
|
|
|
Would you like me to:
|
|
- Generate a Parser class?
|
|
- Set up example tests?
|
|
- Add configuration pattern?
|
|
```
|
|
|
|
## Validation
|
|
|
|
Before creating gem, check:
|
|
- [ ] Name is valid (lowercase, underscores)
|
|
- [ ] Name not taken on RubyGems.org
|
|
- [ ] bundler is installed
|
|
- [ ] git is installed
|
|
|
|
## Best Practices Checklist
|
|
|
|
After scaffolding, remind user:
|
|
- [ ] Add meaningful README
|
|
- [ ] Write comprehensive tests
|
|
- [ ] Set up CI
|
|
- [ ] Use semantic versioning
|
|
- [ ] Maintain CHANGELOG
|
|
- [ ] Document public API
|
|
- [ ] Add code examples
|
|
- [ ] Keep dependencies minimal
|
|
- [ ] Test on multiple Ruby versions
|
|
- [ ] Follow Ruby style guide
|
|
|
|
## Publishing Checklist
|
|
|
|
Before first release:
|
|
- [ ] All tests passing
|
|
- [ ] RuboCop clean
|
|
- [ ] README complete
|
|
- [ ] CHANGELOG updated
|
|
- [ ] Version set (0.1.0)
|
|
- [ ] RubyGems.org account ready
|
|
- [ ] Git repository pushed
|
|
|
|
```bash
|
|
# Setup RubyGems credentials
|
|
curl -u username https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
|
|
chmod 0600 ~/.gem/credentials
|
|
|
|
# Release
|
|
rake release
|
|
```
|