rails-knowledge-patch

Installation
SKILL.md

Ruby on Rails Knowledge Patch

Covers Rails 8.0–8.1 changes. Training cutoff: Rails 7.1, Ruby 3.3.

Index

Topic Reference Key features
Rails 8.0 architecture references/rails-8-architecture.md Solid Queue/Cache/Cable, Kamal 2, Propshaft, auth generator, Turbo morphing
Active Record queries & schema references/active-record-queries.md params.expect, pluck hash, UPDATE with JOIN, first/last deprecation, schema sorting
Active Record columns & serialization references/active-record-columns.md only_columns, update_column touch, serialized comparable, JSON coder, PG 18 virtual columns
Database configuration references/database-config.md Connection pool options, transaction isolation, SQLite extensions, invisible indexes
Active Job continuations references/active-job-continuations.md Resumable multi-step jobs with cursor tracking
Tooling & framework references/tooling.md Local CI, credentials:fetch, structured events, markdown rendering, deprecated associations
Deprecations & removals references/deprecations.md sidekiq adapter, ActiveSupport::Configurable, mb_chars, Active Storage Azure

Rails 8.0 — No Redis, No Sprockets, No Traefik

Rails 8.0 removes external dependencies:

  • Solid Queue replaces Sidekiq/Resque as default Active Job backend (database-backed, FOR UPDATE SKIP LOCKED)
  • Solid Cache replaces Redis/Memcached for fragment caching
  • Solid Cable replaces Redis for Action Cable pub/sub
  • Propshaft replaces Sprockets (digest stamping only, no transpilation)
  • Kamal 2 replaces Capistrano/manual deployment (with kamal-proxy instead of Traefik)
  • Authentication generator (rails generate authentication) — session-based, password-resettable
  • Turbo 8 morphingturbo_refreshes_with method: :morph, scroll: :preserve for DOM morphing
  • allow_browser guard — allow_browser versions: :modern returns 406 for old browsers
  • Thruster — HTTP/2 proxy in Dockerfile for asset caching/compression

See references/rails-8-architecture.md for full details, configuration, and code examples.

Quick Reference

params.expect replaces require/permit (8.0)

# New preferred way (safer, more explicit)
params.expect(post: [:title, :body])
# replaces: params.require(:post).permit(:title, :body)

SQLite virtual tables (8.0)

create_virtual_table :posts_search, :fts5, ["content", "title"]

Custom batch columns (8.0)

Product.in_batches(cursor: [:shop_id, :id]) do |relation|
  # batches using composite cursor
end

Pluck with hash for joined tables (8.0)

Post.joins(:comments).pluck(:id, comments: :id)

db:migrate on fresh database (8.0)

db:migrate on a fresh database now loads the schema first, then runs only pending migrations. Use db:migrate:reset for the old behavior.

Active Job Continuations (8.1)

Long-running jobs broken into resumable steps via ActiveJob::Continuable:

class ProcessImportJob < ApplicationJob
  include ActiveJob::Continuable

  def perform(import_id)
    step :validate do
      # runs once
    end

    step :process do |step|
      Record.find_each(start: step.cursor) do |record|
        record.process
        step.advance! from: record.id
      end
    end

    step :finalize  # calls private method
  end
end

Structured Event Reporting (8.1)

Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
Rails.event.tagged("graphql") { Rails.event.notify("query.executed", duration: 42) }
Rails.event.set_context(request_id: "abc123", shop_id: 456)

Connection pool configuration (8.1)

production:
  adapter: postgresql
  max_connections: 10 # renamed from pool (old name still works)
  min_connections: 2
  keepalive: 300
  max_age: 600

Transaction isolation (8.1)

ActiveRecord.with_transaction_isolation_level(:read_committed) do
  Tag.create!  # uses read_committed isolation
end
# Also: connection.current_transaction.isolation

Deprecated associations (8.1)

has_many :posts, deprecated: true                       # warn mode (default)
has_many :posts, deprecated: { mode: :raise }           # or :notify
has_many :posts, deprecated: { mode: :warn, backtrace: true }

Reports all usage: author.posts, author.preload(:posts), nested attributes, etc.

only_columns — inverse of ignored_columns (8.1)

class User < ApplicationRecord
  self.only_columns = %w[id name email]
end

UPDATE with JOIN — PostgreSQL & SQLite3 (8.1)

Comment.joins(:post).update_all("title = posts.title")

Previously MySQL-only. Now works for PostgreSQL and SQLite3 (without LIMIT/ORDER/GROUP BY).

Local CI (8.1)

# config/ci.rb — run with bin/ci
CI.run do
  step "Setup", "bin/setup --skip-server"
  step "Style: Ruby", "bin/rubocop"
  step "Tests: Rails", "bin/rails test"

  if success?
    step "Signoff", "gh signoff"
  else
    failure "CI failed.", "Fix the issues and try again."
  end
end

credentials:fetch command (8.1)

rails credentials:fetch kamal.registry_password
# Useful in .kamal/secrets:
# KAMAL_REGISTRY_PASSWORD=$(rails credentials:fetch kamal.registry_password)

update_column with touch (8.1)

user.update_column(:nice, true, touch: true)        # also updates updated_at
user.update_columns(last_ip: request.remote_ip, touch: true)

Serialized comparable attributes (8.1)

serialize :config, type: Hash, coder: JSON, comparable: true  # avoids false dirty tracking

SQLite extensions in database.yml (8.1)

development:
  adapter: sqlite3
  extensions:
    - SQLean::UUID # module responding to .to_path
    - .sqlpkg/nalgeon/crypto/crypto.so # filesystem path

PG 18 virtual generated columns (8.1)

create_table :users do |t|
  t.string :name
  t.virtual :lower_name, type: :string, as: "LOWER(name)"          # virtual on PG 18+
  t.virtual :name_length, type: :integer, as: "LENGTH(name)", stored: true
end

first/last without order deprecated (8.1)

# config/application.rb (Rails 8.1 default)
config.active_record.raise_on_missing_required_finder_order_columns = true

Raises ActiveRecord::MissingRequiredOrderError if no order, implicit_order_column, query_constraints, or primary_key.

New exception classes (8.1)

  • ActiveRecord::CheckViolation — check constraint violations
  • ActiveRecord::ExclusionViolation — PostgreSQL exclusion constraint violations

Key changes summary

Feature Version Area
Solid Queue/Cache/Cable defaults 8.0 Infrastructure
Kamal 2 deployment 8.0 Deployment
Propshaft asset pipeline 8.0 Assets
Authentication generator 8.0 Security
Turbo 8 morphing 8.0 Hotwire
allow_browser guard 8.0 Security
params.expect 8.0 Controllers
SQLite virtual tables 8.0 Active Record
Custom batch cursors 8.0 Active Record
Pluck with hash 8.0 Active Record
db:migrate loads schema first 8.0 Migrations
Job continuations 8.1 Active Job
Structured events 8.1 Framework
Local CI (bin/ci) 8.1 Tooling
Markdown rendering 8.1 Action View
credentials:fetch 8.1 Tooling
Deprecated associations 8.1 Active Record
only_columns 8.1 Active Record
update_column touch 8.1 Active Record
Connection pool config 8.1 Database
Transaction isolation 8.1 Active Record
Serialized comparable 8.1 Active Record
JSON coder options 8.1 Active Record
SQLite extensions in YAML 8.1 Database
Invisible indexes 8.1 MySQL/MariaDB
first/last without order deprecated 8.1 Active Record
UPDATE with JOIN (PG/SQLite) 8.1 Active Record
PG 18 virtual generated columns 8.1 PostgreSQL
Schema columns sorted 8.1 Migrations
New exception classes 8.1 Active Record
Related skills
Installs
3
GitHub Stars
19
First Seen
Apr 7, 2026