All skills
sergiodxa avatar

/ruby-on-rails-best-practices

@102fba6

Ruby on Rails architecture and coding patterns from Basecamp. Use when writing, reviewing, or refactoring Rails code to follow proven conventions for models, controllers, jobs, and concerns. Triggers on tasks involving Rails models, concerns, controllers, background jobs, or Turbo/Hotwire.

Use this Skill: https://skilld.dev/gh/sergiodxa/agent-skills/ruby-on-rails-best-practices

This session only. Nothing lands on disk.

rulesmodel-scoped-concerns.md

≈947 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Use Model-Scoped Concerns

Place concerns specific to a single model in a subdirectory named after the model (app/models/model_name/), not in the shared app/models/concerns/ directory.

Why

  • Co-location: Related code lives together, making it easier to understand a model's full behavior
  • Namespace clarity: Card::Closeable clearly belongs to Card, not a shared utility
  • Avoid bloated concerns directory: The shared concerns folder stays small and truly reusable
  • Natural discovery: When exploring a model, you immediately see all its behaviors in its directory

Directory Structure

app/models/
├── card.rb
├── card/
│   ├── closeable.rb          # Card::Closeable
│   ├── assignable.rb         # Card::Assignable
│   ├── searchable.rb         # Card::Searchable (overrides shared)
│   └── activity_spike/
│       └── detector.rb       # Card::ActivitySpike::Detector (service)
├── user.rb
├── user/
│   ├── avatar.rb             # User::Avatar
│   ├── notifiable.rb         # User::Notifiable
│   └── role.rb               # User::Role
├── concerns/                  # Only truly shared concerns
│   ├── searchable.rb         # Generic Searchable (template)
│   └── mentions.rb           # Generic Mentions (template)

Bad: Everything in Shared Concerns

# app/models/concerns/card_closeable.rb
module CardCloseable
  extend ActiveSupport::Concern
  # ...
end

# app/models/concerns/card_assignable.rb
module CardAssignable
  extend ActiveSupport::Concern
  # ...
end

# app/models/card.rb
class Card < ApplicationRecord
  include CardCloseable, CardAssignable
end

Problems:

  • Concerns directory becomes a dumping ground
  • Naming requires prefixes to avoid collisions
  • Hard to see what behaviors a model has without searching

Good: Model-Scoped Concerns

# app/models/card/closeable.rb
module Card::Closeable
  extend ActiveSupport::Concern

  included do
    has_one :closure, dependent: :destroy

    scope :closed, -> { joins(:closure) }
    scope :open, -> { where.missing(:closure) }
  end

  def closed?
    closure.present?
  end

  def close
    create_closure!
  end

  def reopen
    closure&.destroy
  end
end

# app/models/card.rb
class Card < ApplicationRecord
  include Closeable, Assignable, Searchable, Watchable
  # Ruby resolves these from Card:: namespace first
end

When to Use Shared Concerns

Place concerns in app/models/concerns/ only when:

  1. Multiple models use identical behavior (not just similar)
  2. The concern provides a template that model-specific concerns override
# app/models/concerns/searchable.rb (shared template)
module Searchable
  extend ActiveSupport::Concern

  included do
    after_save_commit :update_search_index
  end

  # Template methods - models override these
  def search_title
    raise NotImplementedError
  end

  def searchable?
    true
  end
end

# app/models/card/searchable.rb (model-specific)
module Card::Searchable
  extend ActiveSupport::Concern

  included do
    include ::Searchable  # Include shared template
  end

  def search_title
    title
  end

  def searchable?
    published?
  end
end

Rules

  1. Default to model-scoped concerns (app/models/model_name/concern.rb)
  2. Name concerns using the model namespace (Card::Closeable, not CardCloseable)
  3. Include without namespace prefix - Ruby resolves Card::Closeable automatically
  4. Use shared concerns only for true cross-model abstractions or templates
  5. Nest service objects and value objects under the model namespace too

Source: SKILL.md on GitHub

1 warning17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides architectural guidelines and coding patterns for Ruby on Rails development based on Basecamp's practices. No security issues were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    17/17 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 102fba6. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 8 months ago

README badge

README badge for sergiodxa/agent-skills/ruby-on-rails-best-practices