ruby-conventions

Service objects, strong params, behavior-focused tests.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ruby-conventions" with this command: npx skills add phrazzld/claude-config/phrazzld-claude-config-ruby-conventions

Ruby Conventions

Service objects, strong params, behavior-focused tests.

Architecture

Service objects for business logic:

app/services/user_registration_service.rb

class UserRegistrationService def initialize(user_params:, mailer: UserMailer) @user_params = user_params @mailer = mailer end

def call user = User.create!(@user_params) @mailer.welcome(user).deliver_later user end end

Thin controllers:

def create user = UserRegistrationService.new(user_params: user_params).call render json: UserSerializer.new(user), status: :created rescue ActiveRecord::RecordInvalid => e render json: { errors: e.record.errors }, status: :unprocessable_entity end

Strong Parameters

Always use strong params. Never mass-assign directly:

Good

def user_params params.require(:user).permit(:email, :name, :password) end

Never

User.create(params[:user]) # SQL injection risk

Query Safety

Always parameterize queries:

Good

User.where(email: email) User.where("email = ?", email)

Never

User.where("email = '#{email}'") # SQL injection

Prevent N+1 queries:

Good

User.includes(:posts).each { |u| u.posts.count }

Bad (N+1)

User.all.each { |u| u.posts.count }

Testing with RSpec

RSpec.describe UserRegistrationService do describe "#call" do it "creates active user with welcome email" do mailer = instance_double(UserMailer) allow(mailer).to receive(:welcome).and_return(double(deliver_later: true))

  service = described_class.new(
    user_params: { email: "test@example.com", name: "Test" },
    mailer: mailer
  )

  user = service.call

  expect(user).to be_persisted
  expect(user.email).to eq("test@example.com")
  expect(mailer).to have_received(:welcome).with(user)
end

end end

Use FactoryBot, not fixtures:

FactoryBot.define do factory :user do email { Faker::Internet.email } name { Faker::Name.name } end end

let(:user) { create(:user) }

API Design

Consistent serialization

class UserSerializer include JSONAPI::Serializer attributes :id, :email, :name, :created_at end

Versioned routes

namespace :api do namespace :v1 do resources :users end end

Language Patterns

Keyword arguments for 2+ params

def send_email(to:, subject:, body:) ... end

Safe navigation

user&.profile&.avatar_url

Frozen strings (file header)

frozen_string_literal: true

Anti-Patterns

  • Fat models (business logic in ActiveRecord)

  • Business logic in controllers

  • Fixtures instead of factories

  • Testing implementation (mocking internals)

  • String interpolation in SQL

  • N+1 queries without includes

  • Synchronous email in request cycle

References

  • rails-performance.md - Caching, background jobs, profiling

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

pencil-renderer

No summary provided by upstream source.

Repository SourceNeeds Review
General

ui-skills

No summary provided by upstream source.

Repository SourceNeeds Review
General

llm-gateway-routing

No summary provided by upstream source.

Repository SourceNeeds Review
General

documentation-standards

No summary provided by upstream source.

Repository SourceNeeds Review