From majestic-rails
Guides Rails code with rubocop-rails-omakase conventions on Turbo Streams, controllers, concerns, services, modern Ruby style, enums, scopes, error handling, and Minitest testing.
npx claudepluginhub majesticlabs-dev/majestic-marketplace --plugin majestic-railsThis skill uses the workspace's default tool permissions.
Opinionated Rails patterns for clean, maintainable code.
Applies Basecamp's Ruby on Rails best practices for models, concerns, controllers, background jobs, and Turbo/Hotwire when writing, reviewing, or refactoring code.
Applies DHH's 37signals Rails style to Ruby code: fat models, thin controllers, Hotwire patterns, REST purity, database constraints, and clarity-over-cleverness. For generation, refactoring, and review.
Provides Ruby on Rails conventions, patterns, and best practices for ActiveRecord models, controllers, migrations, configuration, background jobs, logging, and request specs.
Share bugs, ideas, or general feedback.
Opinionated Rails patterns for clean, maintainable code.
Duplication > Complexity: Simple duplicated code beats complex DRY abstractions
Testability = Quality: If it's hard to test, structure needs refactoring
Adding controllers is never bad. Making controllers complex IS bad.
Simple turbo streams MUST be inline in controllers:
# FAIL: Separate .turbo_stream.erb files for simple operations
render "posts/update"
# PASS: Inline array
render turbo_stream: [
turbo_stream.replace("post_#{@post.id}", partial: "posts/post", locals: { post: @post }),
turbo_stream.remove("flash")
]
Business logic belongs in models or concerns, not controllers.
# Concern structure
module Dispatchable
extend ActiveSupport::Concern
included do
scope :available, -> { where(status: "pending") }
end
class_methods do
def claim!(batch_size)
# class-level behavior
end
end
end
Extract when you see MULTIPLE of:
Service structure:
Extraction::RegexExtractor)# Hash shorthand
{ id:, slug:, doc_type: kind }
# Safe navigation
created_at&.iso8601
@setting ||= SlugSetting.active.find_by!(slug:)
# Keyword arguments
def extract(document_type:, subject:, filename:)
def process!(strategy: nil)
# Frozen arrays with validation
STATUSES = %w[processed needs_review].freeze
enum :status, STATUSES.index_by(&:itself), validate: true
# Guard with .present?, chainable design
scope :by_slug, ->(slug) { where(slug:) if slug.present? }
scope :from_date, ->(date) { where(created_at: Date.parse(date).beginning_of_day..) if date.present? }
def self.filtered(params)
all.by_slug(params[:slug]).by_kind(params[:kind])
rescue ArgumentError
all
end
# Domain-specific errors
class InactiveSlug < StandardError; end
# Log with context, re-raise for upstream
def handle_exception!(error:)
log_error("Exception #{error.class}: #{error.message}", error:)
mark_failed!(error.message)
raise
end
test "describes expected behavior" do
email = emails(:two)
email.process
email.reload
assert_equal "finished", email.processing_status
end
Principles:
emails(:two) for setup.reload after operationsbuild_valid_email, with_stubbed_downloadIf you can't understand in 5 seconds:
# FAIL
show_in_frame
process_stuff
# PASS
fact_check_modal
_fact_frame