SuperAPI AI Directory

ruby-on-rails

Coding & development

View repository

Updated 10-15 20:31

About this skill

Ruby on Rails 8.1

Convention over configuration. New code: Rails 8.1 + Ruby 3.4 when the project allows it. Pure language: skill ruby. Preserve existing Rails 7.x; no “drive-by upgrade”.

Stack and scope

Ask Role
Rails 8.1 Router, MVC, generators
Active Record Persistence, migrations
Propshaft Assets (default 8)
Hotwire Turbo + Stimulus in HTML apps
Solid Queue / Cache / Cable Jobs, cache, DB-backed pubsub
Kamal Deploy (if scope includes it)
Credentials / ENV Secrets

Separate frontend (SPA/mobile): --api or config.api_only. Do not force Turbo into a JSON API.

Organization

app/
  controllers/
  models/
  views/           # omitido em api_only
  jobs/
  mailers/
  policies/        # se o projeto usa Pundit/ActionPolicy
  services/        # POROs de caso de uso (quando o model engordar)
config/
db/migrate/
test/  # ou spec/
  • Fat models with care: validations and invariants in the model; multi-model orchestration in service/PORO.
  • app/services is not a trash can — one object per use case.
  • Concerns only for real duplication, not to hide god objects.

Non-negotiable rules

  • Strong parameters on every controller input.
  • Authz on the server (Pundit/ActionPolicy/scopes); never just hide the button in the view.
  • SQL: query methods / binds; never interpolate input into an SQL string.
  • Reversible migrations when possible; do not edit a migration already applied in production.
  • Secrets: Rails.application.credentials or ENV — never commit keys.
  • CSRF enabled in HTML; APIs with explicit token/session.
  • Idempotent jobs; serializable arguments (IDs, not giant AR objects).

Controllers and routes

class PostsController < ApplicationController
  before_action :set_post, only: %i[show update destroy]

  def create
    @post = Current.user.posts.build(post_params)
    if @post.save
      redirect_to @post
    else
      render :new, status: :unprocessable_content
    end
  end

  private

  def set_post
    @post = Current.user.posts.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:title, :body)
  end
end
  • Scoping by user/tenant in the find — Post.find(params[:id]) on a private resource is IDOR.
  • Correct HTTP statuses (404, 401, 403, 422).
  • JSON: jbuilder / alba / project serializers; not as_json loose with internal columns.
  • Current attributes for request store (user, request_id) — automatic reset.

Active Record

  • Validations + database constraints (unique, FK, check).
  • has_many / belongs_to with inverse_of when cycles get in the way.
  • N+1: includes / preload / strict_loading in dev.
  • Enums, normalizes, composed_of when the domain calls for it.
  • Transactions for composite writes.
  • Queries: chainable scopes; find_by! when absence is an error.

Hotwire (HTML)

  • Turbo Drive/Frames/Streams for UX without an SPA.
  • Stimulus for minimal JS (clipboard, toggle) — business logic stays on the server.
  • turbo_stream responses as needed; do not replace the app with a React SPA without being asked.
  • Forms: form_with, errors in the model, status: :unprocessable_content.

Jobs, mailers, realtime

  • Solid Queue (default 8) unless the repo already uses Sidekiq/GoodJob — do not swap the backend in a feature.
  • deliver_later in mailers; previews in ActionMailer::Preview.
  • Solid Cable / Solid Cache when 8 already configured it; Redis only if it is already the standard.

Frontend and API

  • HTML+Hotwire: views + partials + thin helpers.
  • API mode: versioning if public (/api/v1); documented token/session auth.
  • Contracts: skill api-design.

Tests

  • Fixtures or FactoryBot — whichever the project uses.
  • Controller/request specs for authz and strong params.
  • Model specs for invariants; system tests (Capybara) for the critical Hotwire flow.
  • bin/rails test / bundle exec rspec in scope.

Deploy

  • Kamal if the repository already has config/deploy.yml or the user asks for deploy.
  • RAILS_MASTER_KEY / credentials per environment.
  • Migrations in the release (kamal / pipeline), not db:migrate forgotten manual.
  • Image: skill docker.

Anti-patterns

  • Post.find(params[:id]) without ownership
  • Cascading AR callbacks (emails, HTTP, jobs) invisible
  • update_all / delete_all without scope
  • Editing an old migration
  • Introducing Sidekiq + Solid Queue together
  • Assuming Webpacker / classic Sprockets in an app 8 (Propshaft)
  • Billing/authz logic only in Stimulus

Integration with other skills

  • Language: ruby
  • HTTP: api-design
  • Authz: authentication-authorization
  • Image: docker
  • Local Compose: docker-compose
  • Go-live: production-readiness

Completion criteria

  • Strong params + authz/scoping on the server
  • New migration if the schema changed
  • Async jobs/mailers for external I/O
  • HTML via Hotwire or JSON API — aligned with the client
  • Tests for the flow and for negative IDOR
  • Secrets out of git