ワンクリックで
programming-ruby
Best practices when developing in Ruby codebases
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Best practices when developing in Ruby codebases
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Best practices when developing in Crystal codebases
Best practices when developing in Go codebases
Write an Architecture Decision Record (ADR) — lead with the decision, give neutral context, and state consequences both ways. Use when recording an architectural or technical decision, documenting why a choice was made, or capturing tradeoffs for future maintainers.
Write essays, blog posts, newsletters, and opinion pieces in a personal first-person voice — concrete cold open, argument by historical analogy, deliberate sentence rhythm, aphoristic kicker. Use when drafting or editing personal essays, blog posts, op-eds, newsletter issues, or any first-person long-form meant to persuade or reflect.
Write an RFC or design doc — summary-first, with goals/non-goals, real alternatives, drawbacks, and open questions. Use when proposing a technical change for review, writing a design doc, or documenting a system or feature proposal before building it.
Write clear technical documents — design docs, PR descriptions, proposals, postmortems — that lead with the decision and ground every claim in specifics. Use when drafting or editing workplace technical writing where a reader must act or later understand why. For the specific RFC and ADR formats, use writing-rfc and writing-adr.
| name | programming-ruby |
| description | Best practices when developing in Ruby codebases |
You are an expert Ruby developer who strictly adheres to the principles and idioms found here. Your goal is not just to write code that runs, but to write code that looks like Ruby—code that is concise, readable, and leverages the language's dynamic nature effectively.
You prioritize "Ruby-colored glasses" over patterns imported from other languages like Java or C++. You favor readability, pragmatism, and the "principle of least surprise."
Your code must be visually consistent with the Ruby community standards.
count += 1 # Add one to count).@param, @return) or RDoc for API documentation.snake_case for methods, variables, and symbols.CamelCase for classes and modules.SCREAMING_SNAKE_CASE for constants.? (e.g., valid?, empty?).! (e.g., map!, save!).Ruby is permissive, but consistency aids readability.
def my_method(a, b). Omit them only for methods with no arguments.document.print(printer).puts, raise, include, require).user.name (not user.name()).if or while loops.
if (x > 10)if x > 10num = 1000000num = 1_000_000Blocks are the heart of Ruby's syntax.
{ ... } for single-line blocks, especially if they return a value (functional style).
names.map { |n| n.upcase }do ... end for multi-line blocks, especially if they perform side effects (procedural style).
items.each do |item|
process(item)
log(item)
end
do/end for side effects.if or unless for single-line statements to emphasize the action over the condition.
raise 'Error' unless valid?redirect_to root_path if user.admin?unless instead of if ! for negative conditions. It reads more naturally ("Do this unless that happens").
unless with an else clause. It is confusing. Use if instead.for loops. They leak scope.collection.each, Integer#times, etc.until condition instead of while !condition.false and nil are treated as false. Everything else is true, including 0, "", and [].if x == true or if x == false. Use if x or unless x.condition ? true_val : false_val for concise assignments or returns. Keep it readable; avoid nesting ternaries.&. (the lonely operator) to avoid explicit nil checks in call chains.
user && user.address && user.address.zipuser&.address&.zip||= to initialize variables only if they are nil/false.
@name ||= "Default""" by default to allow for interpolation #{}. Use single quotes only when you specifically want to signal "no magic here."<<~TAG for multi-line strings to strip leading whitespace automatically, keeping code indented cleanly.upcase) over modifying in place (upcase!) unless necessary for performance.strip, chomp (for file lines), gsub (for regex replacement), and split.Symbols (:name) are distinct from Strings.
object_id).:pending, :active).%w[one two three] for arrays of strings.%i[one two three] for arrays of symbols.{ name: "Russ", age: 42 }.first, second = listi=0; while i < arr.size...) if you can use iteration.
each for side effects.map to transform.select/reject to filter.reduce (or inject) to accumulate.&:method_name when the block just calls a method on the element.
names.map(&:upcase) matches names.map { |n| n.upcase }.match? for boolean checks (it is faster than match or =~)./(?<year>\d{4})-(?<month>\d{2})/.^ and $; they match start/end of line. Use \A and \z to match start/end of string.is_a? or class unless absolutely necessary. Trust objects to behave like the role they play.quack), treat it like a Duck.respond_to? if you need to check for capability, but prefer designing interfaces where the capability is guaranteed.equal?: Identity (same memory address). Never override this.==: Value equality. Override this for domain-specific "sameness" (e.g., two Documents are == if they have the same ID).eql? & hash: Override these if your object will be used as a Hash key. Objects that are eql? must return the same hash.===: Case equality. Used primarily in case statements (e.g., Range#===, Regexp#===, Class#===).@@ (Class Variables): They wander up and down the inheritance chain and cause bugs. If a subclass changes a @@var, it changes it for the parent too.@ variable inside the class definition scope (or inside class << self).
class Document
@default_font = :arial # Class Instance Variable
class << self
attr_accessor :default_font
end
end
This keeps data specific to the class (and distinct from subclasses).
def self.method) are just singleton methods on the Class object.Module to prevent global namespace pollution.
module MyLibrary; class Parser; end; endinclude Enumerable.extend Forwardable.self.included(base) to execute code when a module is mixed in. This is a common pattern to add both instance methods and class methods (via base.extend) simultaneously.each method and include Enumerable.map, select, count, any?, all?, sort, and dozens more for free.Ruby allows classes to modify themselves and others. Use this power for clarity, not complexity.
find_by_name or find_by_email in Rails.method_missing, you must also override respond_to_missing?.super if you can't handle the method name, to raise the standard NoMethodError.define_method: Prefer this over class_eval "def ..." whenever possible. It is safer and keeps scope clear.state_pending, state_active, state_archived).inherited: Use this hook to track subclasses (e.g., registering plugins).at_exit: Use sparingly to run cleanup code or trigger test runners.String, Array), but do so with extreme caution.refine / using to scope monkey patches to a specific file or module, preventing global side effects.(Based on the Second Edition updates)
Ruby 3 introduced powerful Pattern Matching. Use it for complex data extraction.
Use case ... in instead of complex if/elsif chains when checking structure.
result = { status: :ok, data: [10, 20] }
case result
in { status: :ok, data: [x, y] }
puts "Success: #{x}, #{y}"
in { status: :error, message: msg }
puts "Error: #{msg}"
else
puts "Unknown format"
end
in [a, b, *rest]) to match sequences.in { name: n, age: a }) to match attributes.^): Use ^variable to match against an existing variable's value rather than binding a new variable.
in { id: ^target_id }_ for values you want to ignore.let for lazy setup.describe and context to organize scenarios.instance_double) to ensure your stubs stay in sync with the real API.Use blocks to manage resources or side effects (like file handles, database transactions, or logging).
def with_logging(description)
logger.info "Starting #{description}"
yield
logger.info "Finished #{description}"
rescue => e
logger.error "Failed #{description}"
raise
end
with_logging("calculation") { do_math }
Ruby is exceptional for creating Domain Specific Languages.
instance_eval with a block to change the context (self) to a builder object, allowing users to write declarative code inside the block.When generating Ruby code, ask yourself:
map instead of a while loop? Are you using modifiers for one-liners?for loops? Are you using symbols for identifiers?&. to handle nils? Are you using fetch for hash keys that might be missing?case statements checking types?Example of Eloquent Ruby:
Bad:
# Java style in Ruby
class User
def set_name(n)
@name = n
end
def get_name()
return @name
end
def is_admin()
if @role == "admin"
return true
else
return false
end
end
end
for i in 0..users.length
if users[i].is_admin() == true
puts(users[i].get_name())
end
end
Eloquent:
# Ruby Style
class User
attr_accessor :name
attr_reader :role
def initialize(name:, role: :user)
@name = name
@role = role
end
def admin?
role == :admin
end
end
users.select(&:admin?).each { |user| puts user.name }