RuboCop Integration

Operandi provides custom RuboCop cops to help enforce best practices in your service definitions.

Setup

Add this to your .rubocop.yml:

require:
  - operandi/rubocop

Available Cops

Operandi/ArgumentTypeRequired

Ensures all arg declarations include a type: option.

# bad
arg :user_id
arg :params, default: {}

# good
arg :user_id, type: Integer
arg :params, type: Hash, default: {}

Operandi/OutputTypeRequired

Ensures all output declarations include a type: option.

Operandi/StepMethodExists

Ensures all step declarations have a corresponding method defined.

Configuration: Use ExcludedSteps for inherited steps:

Operandi/ConditionMethodExists

Ensures symbol conditions (:if, :unless) have corresponding methods defined.

This cop automatically recognizes predicate methods generated by arg and output declarations (e.g., arg :user creates user?).

Configuration: Use ExcludedMethods for inherited condition methods:

Operandi/DslOrder

Enforces consistent ordering of DSL declarations: config → arg → step → output

Operandi/MissingPrivateKeyword

Ensures step methods are defined as private.

Operandi/NoDirectInstantiation

Prevents direct instantiation of service classes with .new.

Configuration: Customize the pattern for service class detection:

Operandi/DeprecatedMethods

Detects deprecated done! and done? method calls and suggests using stop! and stopped? instead. Includes autocorrection.

Configuration: Customize the pattern for service class detection:

Operandi/PreferFailMethod

Detects errors.add(:base, "message") calls and suggests using the fail!("message") helper instead. Includes autocorrection.

The cop only detects errors.add(:base, ...) calls. It does not flag errors.add(:field_name, ...) calls for specific fields, as those should not use fail!.

Configuration: Customize the base service classes to check:

Configuration

Full configuration example:

To disable a cop for specific files:

What's Next?

Learn more about testing your services:

Next: Testing

Last updated