rails-generators
Create expert-level Ruby on Rails generators for models, services, controllers, and full-stack features. Use when building custom generators, scaffolds, or code generation tools for Rails applications, or when the user mentions Rails generators, Thor DSL, or automated code generation.
What this skill does
<objective>
Build production-ready Rails generators that automate repetitive coding tasks and enforce architectural patterns. This skill covers creating custom generators for models, service objects, API scaffolds, and complete features with migrations, tests, and documentation.
</objective>
<quick_start>
<basic_generator>
Create a simple service object generator:
```ruby
# lib/generators/service/service_generator.rb
module Generators
class ServiceGenerator < Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)
def create_service_file
template 'service.rb.tt', "app/services/#{file_name}_service.rb"
end
def create_service_test
template 'service_test.rb.tt', "test/services/#{file_name}_service_test.rb"
end
end
end
```
Template file (templates/service.rb.tt):
```ruby
class <%= class_name %>Service
def initialize
end
def call
# Implementation goes here
end
end
```
Invoke with: `rails generate service payment_processor`
</basic_generator>
<usage_pattern>
**Generator location**: `lib/generators/[name]/[name]_generator.rb`
**Template location**: `lib/generators/[name]/templates/`
**Test location**: `test/generators/[name]_generator_test.rb`
</usage_pattern>
</quick_start>
<context>
<when_to_create>
Create custom generators when you need to:
- **Enforce architectural patterns**: Service objects, form objects, presenters, query objects
- **Reduce boilerplate**: API controllers with standard CRUD, serializers, policy objects
- **Maintain consistency**: Team conventions for file structure, naming, and organization
- **Automate complex setup**: Multi-file features with migrations, tests, and documentation
- **Override Rails defaults**: Customize scaffold behavior for your application's needs
</when_to_create>
<rails_8_updates>
Rails 8 introduced the authentication generator (`rails generate authentication`) which demonstrates modern generator patterns including ActionCable integration, controller concerns, mailer generation, and comprehensive view scaffolding. Study Rails 8 built-in generators for current best practices.
</rails_8_updates>
</context>
<workflow>
<step_1>
**Choose base class**:
- `Rails::Generators::Base`: Simple generators without required arguments
- `Rails::Generators::NamedBase`: Generators requiring a name argument (provides `name`, `class_name`, `file_name`, `plural_name`)
```ruby
class ServiceGenerator < Rails::Generators::NamedBase
# Automatically provides: name, class_name, file_name, plural_name
end
```
</step_1>
<step_2>
**Define source root and options**:
```ruby
source_root File.expand_path('templates', __dir__)
class_option :namespace, type: :string, default: nil, desc: "Namespace for the service"
class_option :skip_tests, type: :boolean, default: false, desc: "Skip test files"
```
Access options with: `options[:namespace]`
</step_2>
<step_3>
**Add public methods** (executed in definition order):
```ruby
def create_service_file
template 'service.rb.tt', service_file_path
end
def create_test_file
return if options[:skip_tests]
template 'service_test.rb.tt', test_file_path
end
private
def service_file_path
if options[:namespace]
"app/services/#{options[:namespace]}/#{file_name}_service.rb"
else
"app/services/#{file_name}_service.rb"
end
end
```
</step_3>
<step_4>
**Create ERB templates** (`.tt` extension):
```erb
<% if options[:namespace] -%>
module <%= options[:namespace].camelize %>
class <%= class_name %>Service
def call
# Implementation
end
end
end
<% else -%>
class <%= class_name %>Service
def call
# Implementation
end
end
<% end -%>
```
**Important**: Use `<%%` to output literal `<%` in generated files. See [references/templates.md](references/templates.md) for template patterns.
</step_4>
<step_5>
**Test the generator** (see [Testing](#testing) section):
```ruby
rails generate service payment_processor --namespace=billing
rails generate service notifier --skip-tests
```
</step_5>
</workflow>
<common_patterns>
<model_generator>
**Custom model with associations and scopes**:
```ruby
class CustomModelGenerator < Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)
class_option :parent, type: :string, desc: "Parent model for belongs_to"
class_option :scope, type: :array, desc: "Scopes to generate"
def create_migration
migration_template 'migration.rb.tt', "db/migrate/create_#{table_name}.rb"
end
def create_model_file
template 'model.rb.tt', "app/models/#{file_name}.rb"
end
end
```
See [references/model-generator.md](references/model-generator.md) for complete example with templates.
</model_generator>
<service_object_generator>
**Service object with result object pattern**:
```ruby
class ServiceGenerator < Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)
class_option :result_object, type: :boolean, default: true
class_option :pattern, type: :string, default: 'simple',
desc: "Service pattern (simple, command, interactor)"
def create_service
template 'service.rb.tt', "app/services/#{file_name}_service.rb"
end
def create_result_object
return unless options[:result_object]
template 'result.rb.tt', "app/services/#{file_name}_result.rb"
end
end
```
See [references/service-generator.md](references/service-generator.md) for complete example with all three patterns.
</service_object_generator>
<api_controller_generator>
**API controller with serializer**:
```ruby
class ApiControllerGenerator < Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)
class_option :serializer, type: :string, default: 'active_model_serializers'
class_option :actions, type: :array, default: %w[index show create update destroy]
def create_controller
template 'controller.rb.tt',
"app/controllers/api/v1/#{file_name.pluralize}_controller.rb"
end
def create_serializer
template "serializer_#{options[:serializer]}.rb.tt",
"app/serializers/#{file_name}_serializer.rb"
end
def add_routes
route "namespace :api do\n namespace :v1 do\n resources :#{file_name.pluralize}\n end\n end"
end
end
```
See [references/api-generator.md](references/api-generator.md) for complete example with templates.
</api_controller_generator>
<full_stack_scaffold>
**Complete feature scaffold** using generator composition:
```ruby
class FeatureGenerator < Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)
class_option :api, type: :boolean, default: false
def create_model
invoke 'model', [name], migration: true
end
def create_controller
if options[:api]
invoke 'api_controller', [name]
else
invoke 'controller', [name], actions: %w[index show new create edit update destroy]
end
end
def create_views
return if options[:api]
%w[index show new edit _form].each do |view|
template "views/#{view}.html.erb.tt",
"app/views/#{file_name.pluralize}/#{view}.html.erb"
end
end
end
```
See [references/scaffold-generator.md](references/scaffold-generator.md) for complete example.
</full_stack_scaffold>
</common_patterns>
<advanced_features>
<hooks>
**Generator hooks** enable modular composition and test framework integration:
```ruby
class ServiceGenerator < Rails::Generators::NamedBase
hook_for :test_framework, as: :service
end
```
This automatically invokes `test_unit:service` or `rspec:service` based on configuration. See [references/hooks.md](references/hooks.md) for hook patterns, responders, and fallback configuration.
</hooks>
<generator_composition>
**Invoke other generators**:
```ruby
def create_dependencies
invoke 'model', [name], migration: true
invoke 'service', ["#{name}_processor"]
invoke 'mailer', [name] if options[:mailer]
end
```
</generator_composition>
<namespacing>
**Namespace generators** for organization:
```ruby
# lib/generatRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.