ruby
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRuby Development Skill
Ruby开发技能
Purpose
用途
This skill provides comprehensive guidance for Ruby development, covering language fundamentals, object-oriented design, error handling, performance optimization, and modern Ruby (3.x+) features. It synthesizes knowledge from Ruby internals, best practices, and official documentation to help Claude write idiomatic, maintainable, and performant Ruby code.
本技能为Ruby开发提供全面指导,涵盖语言基础、面向对象设计、错误处理、性能优化以及现代Ruby(3.x及以上)特性。它整合了Ruby内部机制、最佳实践和官方文档的知识,帮助Claude编写符合Ruby风格、可维护且高性能的代码。
When to Use This Skill
何时使用本技能
Use this skill when:
- Writing or reviewing Ruby code
- Debugging Ruby applications
- Optimizing Ruby performance
- Implementing object-oriented designs
- Handling errors and exceptions
- Working with Ruby's standard library
- Using modern Ruby features (pattern matching, types, fibers, ractors)
- Building Rails applications or Ruby gems
在以下场景使用本技能:
- 编写或评审Ruby代码
- 调试Ruby应用
- 优化Ruby性能
- 实现面向对象设计
- 处理错误与异常
- 使用Ruby标准库
- 使用现代Ruby特性(模式匹配、类型、Fibers、Ractors)
- 构建Rails应用或Ruby gems
Ruby Philosophy and Core Principles
Ruby设计理念与核心原则
Matz's Design Philosophy
Matz的设计哲学
Ruby is designed to make programmers happy. It prioritizes:
- Developer Productivity - Write less code to accomplish more
- Readability - Code should read like natural language
- Flexibility - Multiple ways to accomplish tasks (TMTOWTDI - There's More Than One Way To Do It)
- Object-Oriented Everything - Everything is an object, including primitives
- Duck Typing - "If it walks like a duck and quacks like a duck, it's a duck"
Ruby的设计目标是让程序员感到愉悦。它优先考虑:
- 开发者生产力 - 用更少的代码完成更多工作
- 可读性 - 代码应像自然语言一样易读
- 灵活性 - 完成任务的方式不止一种(TMTOWTDI - There's More Than One Way To Do It)
- 万物皆对象 - 所有事物都是对象,包括基本类型
- 鸭子类型 - "如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"
Ruby's Core Characteristics
Ruby的核心特性
ruby
undefinedruby
undefinedEverything is an object
Everything is an object
5.times { puts "Hello" } # Integer is an object
"hello".upcase # String is an object
nil.class # => NilClass
5.times { puts "Hello" } # Integer is an object
"hello".upcase # String is an object
nil.class # => NilClass
Blocks are first-class citizens
Blocks are first-class citizens
[1, 2, 3].map { |n| n * 2 } # => [2, 4, 6]
[1, 2, 3].map { |n| n * 2 } # => [2, 4, 6]
Open classes - can modify any class
Open classes - can modify any class
class String
def shout
"#{upcase}!"
end
end
"hello".shout # => "HELLO!"
class String
def shout
"#{upcase}!"
end
end
"hello".shout # => "HELLO!"
Duck typing - focus on behavior, not type
Duck typing - focus on behavior, not type
def process(thing)
thing.call if thing.respond_to?(:call)
end
undefineddef process(thing)
thing.call if thing.respond_to?(:call)
end
undefinedObject-Oriented Design in Ruby
Ruby中的面向对象设计
The Ruby Object Model
Ruby对象模型
Understanding Ruby's object model is crucial for effective programming:
ruby
undefined理解Ruby的对象模型是高效编程的关键:
ruby
undefinedClass hierarchy
Class hierarchy
class Animal
def speak
"Some sound"
end
end
class Dog < Animal
def speak
"Woof!"
end
end
class Animal
def speak
"Some sound"
end
end
class Dog < Animal
def speak
"Woof!"
end
end
Every class is an instance of Class
Every class is an instance of Class
Dog.class # => Class
Dog.superclass # => Animal
Animal.superclass # => Object
Object.superclass # => BasicObject
Dog.class # => Class
Dog.superclass # => Animal
Animal.superclass # => Object
Object.superclass # => BasicObject
Singleton methods (eigenclass/metaclass)
Singleton methods (eigenclass/metaclass)
dog = Dog.new
def dog.name
"Buddy"
end
dog.name # => "Buddy"
Dog.new.name # NoMethodError
undefineddog = Dog.new
def dog.name
"Buddy"
end
dog.name # => "Buddy"
Dog.new.name # NoMethodError
undefinedComposition Over Inheritance
组合优于继承
Prefer composition and modules over deep inheritance hierarchies:
ruby
undefined优先使用组合和模块,而非深层继承体系:
ruby
undefined❌ Bad: Deep inheritance
❌ 不良实践:深层继承
class Vehicle
end
class LandVehicle < Vehicle
end
class Car < LandVehicle
end
class SportsCar < Car
end
class Vehicle
end
class LandVehicle < Vehicle
end
class Car < LandVehicle
end
class SportsCar < Car
end
✅ Good: Composition with modules
✅ 良好实践:使用模块进行组合
module Drivable
def drive
"Driving..."
end
end
module Flyable
def fly
"Flying..."
end
end
class Car
include Drivable
end
class Plane
include Flyable
include Drivable # Can taxi on ground
end
undefinedmodule Drivable
def drive
"Driving..."
end
end
module Flyable
def fly
"Flying..."
end
end
class Car
include Drivable
end
class Plane
include Flyable
include Drivable # 可在地面滑行
end
undefinedSingle Responsibility Principle
单一职责原则
Each class should have one reason to change:
ruby
undefined每个类应该只有一个引起变化的原因:
ruby
undefined❌ Bad: Multiple responsibilities
❌ 不良实践:多职责
class User
def save
# Database logic
end
def send_email
# Email logic
end
def generate_report
# Report logic
end
end
class User
def save
# 数据库逻辑
end
def send_email
# 邮件逻辑
end
def generate_report
# 报表逻辑
end
end
✅ Good: Separate concerns
✅ 良好实践:分离关注点
class User
def save
UserRepository.new.save(self)
end
end
class UserMailer
def send_welcome_email(user)
# Email logic
end
end
class UserReportGenerator
def generate(user)
# Report logic
end
end
undefinedclass User
def save
UserRepository.new.save(self)
end
end
class UserMailer
def send_welcome_email(user)
# 邮件逻辑
end
end
class UserReportGenerator
def generate(user)
# 报表逻辑
end
end
undefinedDependency Injection
依赖注入
Inject dependencies rather than hardcoding them:
ruby
undefined注入依赖而非硬编码:
ruby
undefined❌ Bad: Hard dependency
❌ 不良实践:硬依赖
class OrderProcessor
def process(order)
PaymentGateway.new.charge(order.amount)
EmailService.new.send_confirmation(order)
end
end
class OrderProcessor
def process(order)
PaymentGateway.new.charge(order.amount)
EmailService.new.send_confirmation(order)
end
end
✅ Good: Dependency injection
✅ 良好实践:依赖注入
class OrderProcessor
def initialize(payment_gateway: PaymentGateway.new,
email_service: EmailService.new)
@payment_gateway = payment_gateway
@email_service = email_service
end
def process(order)
@payment_gateway.charge(order.amount)
@email_service.send_confirmation(order)
end
end
undefinedclass OrderProcessor
def initialize(payment_gateway: PaymentGateway.new,
email_service: EmailService.new)
@payment_gateway = payment_gateway
@email_service = email_service
end
def process(order)
@payment_gateway.charge(order.amount)
@email_service.send_confirmation(order)
end
end
undefinedLaw of Demeter (Principle of Least Knowledge)
迪米特法则(最少知识原则)
Avoid reaching through multiple objects:
ruby
undefined避免链式调用多个对象:
ruby
undefined❌ Bad: Train wreck
❌ 不良实践:调用链混乱
customer.orders.last.line_items.first.price
customer.orders.last.line_items.first.price
✅ Good: Delegate or encapsulate
✅ 良好实践:委托或封装
class Customer
def last_order_first_item_price
orders.last&.first_item_price
end
end
class Order
def first_item_price
line_items.first&.price
end
end
customer.last_order_first_item_price
undefinedclass Customer
def last_order_first_item_price
orders.last&.first_item_price
end
end
class Order
def first_item_price
line_items.first&.price
end
end
customer.last_order_first_item_price
undefinedError Handling and Exceptions
错误处理与异常
The Exception Hierarchy
异常层级
Exception
├── NoMemoryError
├── ScriptError
│ ├── LoadError
│ ├── NotImplementedError
│ └── SyntaxError
├── SignalException
│ └── Interrupt
├── StandardError (Default rescue catches this)
│ ├── ArgumentError
│ ├── IOError
│ │ └── EOFError
│ ├── IndexError
│ ├── LocalJumpError
│ ├── NameError
│ │ └── NoMethodError
│ ├── RangeError
│ ├── RegexpError
│ ├── RuntimeError (Default raise creates this)
│ ├── SecurityError
│ ├── SystemCallError
│ ├── ThreadError
│ ├── TypeError
│ └── ZeroDivisionError
├── SystemExit
└── SystemStackErrorException
├── NoMemoryError
├── ScriptError
│ ├── LoadError
│ ├── NotImplementedError
│ └── SyntaxError
├── SignalException
│ └── Interrupt
├── StandardError (默认rescue捕获此类)
│ ├── ArgumentError
│ ├── IOError
│ │ └── EOFError
│ ├── IndexError
│ ├── LocalJumpError
│ ├── NameError
│ │ └── NoMethodError
│ ├── RangeError
│ ├── RegexpError
│ ├── RuntimeError (默认raise创建此类)
│ ├── SecurityError
│ ├── SystemCallError
│ ├── ThreadError
│ ├── TypeError
│ └── ZeroDivisionError
├── SystemExit
└── SystemStackErrorException Handling Best Practices
异常处理最佳实践
1. Exceptions Should Be Exceptional
1. 异常应用于异常场景
Use exceptions for exceptional cases, not control flow:
ruby
undefined仅在异常情况下使用异常,而非控制流程:
ruby
undefined❌ Bad: Using exceptions for control flow
❌ 不良实践:用异常做控制流程
def find_user(id)
user = User.find(id)
rescue ActiveRecord::RecordNotFound
nil
end
def find_user(id)
user = User.find(id)
rescue ActiveRecord::RecordNotFound
nil
end
✅ Good: Use explicit checks
✅ 良好实践:使用显式检查
def find_user(id)
User.find_by(id: id)
end
undefineddef find_user(id)
User.find_by(id: id)
end
undefined2. Rescue Specific Exceptions
2. 捕获特定异常
Always rescue specific exceptions, never bare rescue:
ruby
undefined始终捕获特定异常,不要使用裸rescue:
ruby
undefined❌ Bad: Catches everything, including SystemExit
❌ 不良实践:捕获所有异常,包括SystemExit
begin
dangerous_operation
rescue
Too broad!
end
begin
dangerous_operation
rescue
范围过广!
end
✅ Good: Rescue specific exceptions
✅ 良好实践:捕获特定异常
begin
dangerous_operation
rescue NetworkError, TimeoutError => e
logger.error("Network issue: #{e.message}")
retry_operation
end
undefinedbegin
dangerous_operation
rescue NetworkError, TimeoutError => e
logger.error("Network issue: #{e.message}")
retry_operation
end
undefined3. Fail Fast, Fail Loudly
3. 快速失败,明确报错
Let errors propagate unless you can handle them meaningfully:
ruby
undefined除非能有意义地处理错误,否则让错误向上传播:
ruby
undefined❌ Bad: Swallowing exceptions
❌ 不良实践:吞噬异常
def process_data(data)
result = parse(data)
rescue => e
nil # Silent failure!
end
def process_data(data)
result = parse(data)
rescue => e
nil # 静默失败!
end
✅ Good: Let it fail or handle meaningfully
✅ 良好实践:让错误传播或进行有意义的处理
def process_data(data)
parse(data)
rescue ParseError => e
logger.error("Failed to parse data: #{e.message}")
raise # Re-raise to propagate
end
undefineddef process_data(data)
parse(data)
rescue ParseError => e
logger.error("Failed to parse data: #{e.message}")
raise # 重新抛出以传播错误
end
undefined4. Use ensure for Cleanup
4. 使用ensure进行清理
Always use for cleanup code:
ensureruby
undefined始终使用执行清理代码:
ensureruby
undefined✅ Proper resource management
✅ 正确的资源管理
def process_file(filename)
file = File.open(filename)
process(file)
ensure
file&.close
end
def process_file(filename)
file = File.open(filename)
process(file)
ensure
file&.close
end
Better: Use blocks that auto-close
更优方式:使用自动关闭的块
def process_file(filename)
File.open(filename) do |file|
process(file)
end # Automatically closed
end
undefineddef process_file(filename)
File.open(filename) do |file|
process(file)
end # 自动关闭文件
end
undefined5. Custom Exceptions for Domain Logic
5. 为领域逻辑创建自定义异常
Create custom exceptions for your domain:
ruby
undefined为业务领域创建自定义异常:
ruby
undefinedDefine custom exceptions
定义自定义异常
class PaymentError < StandardError; end
class InsufficientFundsError < PaymentError; end
class InvalidCardError < PaymentError; end
class PaymentError < StandardError; end
class InsufficientFundsError < PaymentError; end
class InvalidCardError < PaymentError; end
Use them meaningfully
有意义地使用它们
def charge_card(card, amount)
raise InvalidCardError, "Card expired" if card.expired?
raise InsufficientFundsError if balance < amount
process_charge(card, amount)
end
def charge_card(card, amount)
raise InvalidCardError, "Card expired" if card.expired?
raise InsufficientFundsError if balance < amount
process_charge(card, amount)
end
Caller can handle appropriately
调用方可针对性处理
begin
charge_card(card, 100)
rescue InsufficientFundsError => e
notify_user("Insufficient funds")
rescue InvalidCardError => e
notify_user("Please update your card")
rescue PaymentError => e
Catch all payment errors
logger.error("Payment failed: #{e.message}")
end
undefinedbegin
charge_card(card, 100)
rescue InsufficientFundsError => e
notify_user("余额不足")
rescue InvalidCardError => e
notify_user("请更新您的银行卡信息")
rescue PaymentError => e
捕获所有支付相关错误
logger.error("Payment failed: #{e.message}")
end
undefined6. The Weirich raise/fail Convention
6. Weirich的raise/fail约定
Use for exceptions you expect to be rescued, for re-raising:
failraiseruby
def process_order(order)
fail ArgumentError, "Order cannot be nil" if order.nil?
begin
payment_gateway.charge(order)
rescue PaymentError => e
logger.error("Payment failed: #{e.message}")
raise # Re-raise with raise
end
end使用表示预期会被捕获的异常,使用表示重新抛出异常:
failraiseruby
def process_order(order)
fail ArgumentError, "Order cannot be nil" if order.nil?
begin
payment_gateway.charge(order)
rescue PaymentError => e
logger.error("Payment failed: #{e.message}")
raise # 使用raise重新抛出
end
end7. Provide Context in Exceptions
7. 在异常中提供上下文信息
Include helpful information in exception messages:
ruby
undefined在异常消息中包含有用的信息:
ruby
undefined❌ Bad: Vague message
❌ 不良实践:模糊的消息
raise "Invalid input"
raise "Invalid input"
✅ Good: Descriptive message with context
✅ 良好实践:带有上下文的描述性消息
raise ArgumentError, "Expected positive integer for age, got: #{age.inspect}"
undefinedraise ArgumentError, "Expected positive integer for age, got: #{age.inspect}"
undefinedAlternative Error Handling Patterns
替代错误处理模式
Result Objects
结果对象
Return result objects instead of raising exceptions:
ruby
class Result
attr_reader :value, :error
def initialize(value: nil, error: nil)
@value = value
@error = error
end
def success?
error.nil?
end
def failure?
!success?
end
end
def divide(a, b)
return Result.new(error: "Division by zero") if b.zero?
Result.new(value: a / b)
end
result = divide(10, 2)
if result.success?
puts result.value
else
puts "Error: #{result.error}"
end返回结果对象而非抛出异常:
ruby
class Result
attr_reader :value, :error
def initialize(value: nil, error: nil)
@value = value
@error = error
end
def success?
error.nil?
end
def failure?
!success?
end
end
def divide(a, b)
return Result.new(error: "Division by zero") if b.zero?
Result.new(value: a / b)
end
result = divide(10, 2)
if result.success?
puts result.value
else
puts "Error: #{result.error}"
endCaller-Supplied Fallback Strategy
调用方提供的回退策略
Let callers define error handling:
ruby
def fetch_user(id, &fallback)
User.find(id)
rescue ActiveRecord::RecordNotFound => e
fallback ? fallback.call(e) : raise
end让调用方定义错误处理逻辑:
ruby
def fetch_user(id, &fallback)
User.find(id)
rescue ActiveRecord::RecordNotFound => e
fallback ? fallback.call(e) : raise
endUsage
使用示例
user = fetch_user(999) { |e| User.new(name: "Guest") }
undefineduser = fetch_user(999) { |e| User.new(name: "Guest") }
undefinedRuby Performance and Optimization
Ruby性能与优化
Understanding Ruby's VM (YARV)
理解Ruby虚拟机(YARV)
Ruby 3.x uses YARV (Yet Another Ruby VM) with JIT compilation:
ruby
undefinedRuby 3.x使用YARV(Yet Another Ruby VM)并支持JIT编译:
ruby
undefinedEnable JIT (YJIT in Ruby 3.1+)
启用JIT(Ruby 3.1+为YJIT)
Run with: ruby --yjit your_script.rb
运行方式:ruby --yjit your_script.rb
Check JIT status
检查JIT状态
puts "JIT enabled: #{defined?(RubyVM::YJIT)}"
puts "JIT enabled: #{defined?(RubyVM::YJIT)}"
Profile JIT compilation
分析JIT编译情况
RubyVM::YJIT.runtime_stats if defined?(RubyVM::YJIT)
undefinedRubyVM::YJIT.runtime_stats if defined?(RubyVM::YJIT)
undefinedMemory Management and Garbage Collection
内存管理与垃圾回收
Ruby uses generational garbage collection:
ruby
undefinedRuby使用分代垃圾回收机制:
ruby
undefinedCheck GC stats
查看GC统计信息
GC.stat
GC.stat
=> {:count=>23, :heap_allocated_pages=>145, ...}
=> {:count=>23, :heap_allocated_pages=>145, ...}
Manual GC control (rarely needed)
手动控制GC(很少需要)
GC.disable # Disable GC temporarily
GC.disable # 临时禁用GC
... do intensive work
... 执行密集型工作
GC.enable
GC.start # Force GC
GC.enable
GC.start # 强制触发GC
Monitor object allocations
监控对象分配
before = GC.stat(:total_allocated_objects)
before = GC.stat(:total_allocated_objects)
... your code
... 你的代码
after = GC.stat(:total_allocated_objects)
puts "Allocated: #{after - before} objects"
undefinedafter = GC.stat(:total_allocated_objects)
puts "Allocated: #{after - before} objects"
undefinedPerformance Best Practices
性能最佳实践
1. Avoid Creating Unnecessary Objects
1. 避免创建不必要的对象
ruby
undefinedruby
undefined❌ Bad: Creates many string objects
❌ 不良实践:创建大量字符串对象
1000.times do |i|
"User #{i}" # New string each time
end
1000.times do |i|
"User #{i}" # 每次创建新字符串
end
✅ Good: Reuse strings with interpolation
✅ 良好实践:使用插值复用字符串
template = "User %d"
1000.times do |i|
template % i
end
template = "User %d"
1000.times do |i|
template % i
end
✅ Even better: Use frozen strings
✅ 更优方式:使用冻结字符串
MESSAGE = "Processing".freeze
undefinedMESSAGE = "Processing".freeze
undefined2. Use Symbols for Repeated Strings
2. 对重复字符串使用符号
ruby
undefinedruby
undefined❌ Bad: Creates new string objects
❌ 不良实践:创建新字符串对象
hash = { "name" => "John", "age" => 30 }
hash = { "name" => "John", "age" => 30 }
✅ Good: Symbols are immutable and reused
✅ 良好实践:符号是不可变且可复用的
hash = { name: "John", age: 30 }
undefinedhash = { name: "John", age: 30 }
undefined3. Prefer Enumerable Methods Over Loops
3. 优先使用Enumerable方法而非循环
ruby
undefinedruby
undefined❌ Bad: Manual loop
❌ 不良实践:手动循环
result = []
array.each do |item|
result << item * 2 if item > 0
end
result = []
array.each do |item|
result << item * 2 if item > 0
end
✅ Good: Chained enumerable methods
✅ 良好实践:链式调用Enumerable方法
result = array.select { |item| item > 0 }
.map { |item| item * 2 }
result = array.select { |item| item > 0 }
.map { |item| item * 2 }
✅ Even better: Single pass with each_with_object
✅ 更优方式:使用each_with_object单次遍历
result = array.each_with_object([]) do |item, acc|
acc << item * 2 if item > 0
end
undefinedresult = array.each_with_object([]) do |item, acc|
acc << item * 2 if item > 0
end
undefined4. Use Lazy Enumerables for Large Collections
4. 对大型集合使用惰性枚举
ruby
undefinedruby
undefined❌ Bad: Creates intermediate arrays
❌ 不良实践:创建中间数组
(1..1_000_000).select { |n| n.even? }
.map { |n| n * 2 }
.first(10)
(1..1_000_000).select { |n| n.even? }
.map { |n| n * 2 }
.first(10)
✅ Good: Lazy evaluation
✅ 良好实践:惰性求值
(1..1_000_000).lazy
.select { |n| n.even? }
.map { |n| n * 2 }
.first(10)
undefined(1..1_000_000).lazy
.select { |n| n.even? }
.map { |n| n * 2 }
.first(10)
undefined5. Cache Expensive Computations
5. 缓存昂贵的计算结果
ruby
undefinedruby
undefined❌ Bad: Recomputes every time
❌ 不良实践:每次都重新计算
class User
def full_name
"#{first_name} #{last_name}".strip
end
end
class User
def full_name
"#{first_name} #{last_name}".strip
end
end
✅ Good: Memoization
✅ 良好实践:记忆化(Memoization)
class User
def full_name
@full_name ||= "#{first_name} #{last_name}".strip
end
end
class User
def full_name
@full_name ||= "#{first_name} #{last_name}".strip
end
end
⚠️ Careful with nil/false values
⚠️ 注意nil/false值的情况
def expensive_check
return @result if defined?(@result)
@result = compute_result
end
undefineddef expensive_check
return @result if defined?(@result)
@result = compute_result
end
undefinedModern Ruby Features (3.x+)
现代Ruby特性(3.x+)
Pattern Matching (Ruby 2.7+)
模式匹配(Ruby 2.7+)
ruby
undefinedruby
undefinedBasic pattern matching
基础模式匹配
case [1, 2, 3]
in [a, b, c]
puts "#{a}, #{b}, #{c}"
end
case [1, 2, 3]
in [a, b, c]
puts "#{a}, #{b}, #{c}"
end
Hash patterns
Hash模式
case { name: "John", age: 30 }
in { name: "John", age: age }
puts "John is #{age}"
in { name:, age: } # Variable punning
puts "#{name} is #{age}"
end
case { name: "John", age: 30 }
in { name: "John", age: age }
puts "John is #{age}"
in { name:, age: } # 变量简写
puts "#{name} is #{age}"
end
Array patterns with rest
带剩余元素的数组模式
case [1, 2, 3, 4, 5]
in [first, *rest, last]
puts "First: #{first}, Last: #{last}, Rest: #{rest}"
end
case [1, 2, 3, 4, 5]
in [first, *rest, last]
puts "First: #{first}, Last: #{last}, Rest: #{rest}"
end
Rightward assignment (Ruby 3.0+)
右向赋值(Ruby 3.0+)
{ name: "John", age: 30 } => { name:, age: }
puts name # => "John"
{ name: "John", age: 30 } => { name:, age: }
puts name # => "John"
Guard clauses
守卫子句
case value
in String => s if s.length > 10
puts "Long string: #{s}"
in String => s
puts "Short string: #{s}"
end
undefinedcase value
in String => s if s.length > 10
puts "Long string: #{s}"
in String => s
puts "Short string: #{s}"
end
undefinedEndless Method Definition (Ruby 3.0+)
无限方法定义(Ruby 3.0+)
ruby
undefinedruby
undefinedTraditional
传统写法
def square(x)
x * x
end
def square(x)
x * x
end
Endless method (for simple one-liners)
无限方法(适用于简单单行方法)
def square(x) = x * x
def full_name = "#{first_name} #{last_name}"
def admin? = role == "admin"
undefineddef square(x) = x * x
def full_name = "#{first_name} #{last_name}"
def admin? = role == "admin"
undefinedNumbered Parameters (Ruby 2.7+)
编号参数(Ruby 2.7+)
ruby
undefinedruby
undefinedTraditional block parameters
传统块参数
[1, 2, 3].map { |n| n * 2 }
[1, 2, 3].map { |n| n * 2 }
Numbered parameters
编号参数
[1, 2, 3].map { _1 * 2 }
[1, 2, 3].map { _1 * 2 }
Multiple numbered parameters
多个编号参数
hash.map { [_1, _2 * 2] }
undefinedhash.map { [_1, _2 * 2] }
undefinedRightward Assignment (Ruby 3.0+)
右向赋值(Ruby 3.0+)
ruby
undefinedruby
undefinedTraditional assignment
传统赋值
result = compute_value()
puts result
result = compute_value()
puts result
Rightward assignment (useful in method chains)
右向赋值(在方法链中很有用)
compute_value() => result
puts result
compute_value() => result
puts result
Useful for debugging
用于调试
calculate_price.tap { p _1 } => price
undefinedcalculate_price.tap { p _1 } => price
undefinedRactors (Ruby 3.0+) - True Parallelism
Ractors(Ruby 3.0+)- 真正的并行性
ruby
undefinedruby
undefinedCreate parallel-safe ractor
创建并行安全的Ractor
r = Ractor.new do
received = Ractor.receive
received * 2
end
r.send(21)
r.take # => 42
r = Ractor.new do
received = Ractor.receive
received * 2
end
r.send(21)
r.take # => 42
Multiple ractors
多个Ractors
results = 4.times.map do |i|
Ractor.new(i) do |n|
# Heavy computation
(1..1000000).reduce(:+) + n
end
end
results.map(&:take) # Runs in parallel
undefinedresults = 4.times.map do |i|
Ractor.new(i) do |n|
# 繁重计算
(1..1000000).reduce(:+) + n
end
end
results.map(&:take) # 并行运行
undefinedTyped Ruby with RBS (Ruby 3.0+)
使用RBS的类型化Ruby(Ruby 3.0+)
ruby
undefinedruby
undefinedDefine types in .rbs files
在.rbs文件中定义类型
user.rbs
user.rbs
class User
attr_reader name: String
attr_reader age: Integer
def initialize: (name: String, age: Integer) -> void
def adult?: () -> bool
end
class User
attr_reader name: String
attr_reader age: Integer
def initialize: (name: String, age: Integer) -> void
def adult?: () -> bool
end
Use TypeProf to generate signatures
使用TypeProf生成签名
$ typeprof user.rb
$ typeprof user.rb
Validate with Steep or RBS
使用Steep或RBS进行验证
$ steep check
$ steep check
undefinedundefinedFiber Scheduler (Ruby 3.0+) - Non-blocking I/O
Fiber调度器(Ruby 3.0+)- 非阻塞I/O
ruby
require 'async'ruby
require 'async'Async execution with fibers
使用Fibers进行异步执行
Async do
Async do
puts "Task 1 start"
sleep 2
puts "Task 1 end"
end
Async do
puts "Task 2 start"
sleep 1
puts "Task 2 end"
end
end
Async do
Async do
puts "Task 1 start"
sleep 2
puts "Task 1 end"
end
Async do
puts "Task 2 start"
sleep 1
puts "Task 2 end"
end
end
Both tasks run concurrently
两个任务并发运行
undefinedundefinedRuby Standard Library Essentials
Ruby标准库要点
Working with Collections
集合操作
ruby
undefinedruby
undefinedArray operations
数组操作
arr = [1, 2, 3, 4, 5]
arr.first(2) # => [1, 2]
arr.last(2) # => [4, 5]
arr.sample # Random element
arr.shuffle # Randomize order
arr.rotate(2) # => [3, 4, 5, 1, 2]
arr.combination(2).to_a # All 2-element combinations
arr.permutation(2).to_a # All 2-element permutations
arr = [1, 2, 3, 4, 5]
arr.first(2) # => [1, 2]
arr.last(2) # => [4, 5]
arr.sample # 随机元素
arr.shuffle # 随机排序
arr.rotate(2) # => [3, 4, 5, 1, 2]
arr.combination(2).to_a # 所有2元素组合
arr.permutation(2).to_a # 所有2元素排列
Hash operations
哈希操作
hash = { a: 1, b: 2, c: 3 }
hash.fetch(:d, 0) # => 0 (default value)
hash.dig(:nested, :key) # Safe nested access
hash.transform_values(&:to_s) # => { a: "1", b: "2", c: "3" }
hash.slice(:a, :b) # => { a: 1, b: 2 }
hash.merge(d: 4) # Non-destructive merge
hash = { a: 1, b: 2, c: 3 }
hash.fetch(:d, 0) # => 0(默认值)
hash.dig(:nested, :key) # 安全的嵌套访问
hash.transform_values(&:to_s) # => { a: "1", b: "2", c: "3" }
hash.slice(:a, :b) # => { a: 1, b: 2 }
hash.merge(d: 4) # 非破坏性合并
Set operations
集合操作
require 'set'
s1 = Set[1, 2, 3]
s2 = Set[2, 3, 4]
s1 | s2 # Union => #<Set: {1, 2, 3, 4}>
s1 & s2 # Intersection => #<Set: {2, 3}>
s1 - s2 # Difference => #<Set: {1}>
undefinedrequire 'set'
s1 = Set[1, 2, 3]
s2 = Set[2, 3, 4]
s1 | s2 # 并集 => #<Set: {1, 2, 3, 4}>
s1 & s2 # 交集 => #<Set: {2, 3}>
s1 - s2 # 差集 => #<Set: {1}>
undefinedString Manipulation
字符串操作
ruby
undefinedruby
undefinedString methods
字符串方法
str = " Hello, World! "
str.strip # => "Hello, World!"
str.split(", ") # => ["Hello", "World!"]
str.gsub("World", "Ruby") # => " Hello, Ruby! "
str.scan(/\w+/) # => ["Hello", "World"]
str.start_with?("Hello") # => false (has spaces)
str.include?("World") # => true
str = " Hello, World! "
str.strip # => "Hello, World!"
str.split(", ") # => ["Hello", "World!"]
str.gsub("World", "Ruby") # => " Hello, Ruby! "
str.scan(/\w+/) # => ["Hello", "World"]
str.start_with?("Hello") # => false(包含空格)
str.include?("World") # => true
String interpolation
字符串插值
name = "John"
age = 30
"#{name} is #{age}" # => "John is 30"
"2 + 2 = #{2 + 2}" # => "2 + 2 = 4"
name = "John"
age = 30
"#{name} is #{age}" # => "John is 30"
"2 + 2 = #{2 + 2}" # => "2 + 2 = 4"
Heredocs
heredoc
text = <<~TEXT
This is a heredoc.
Indentation is removed.
Very useful for multi-line strings.
TEXT
text = <<~TEXT
This is a heredoc.
Indentation is removed.
Very useful for multi-line strings.
TEXT
Frozen strings (immutable)
冻结字符串(不可变)
CONSTANT = "immutable".freeze
CONSTANT = "immutable".freeze
Or with magic comment:
或使用魔法注释:
frozen_string_literal: true
frozen_string_literal: true
undefinedundefinedFile I/O
文件I/O
ruby
undefinedruby
undefinedReading files
读取文件
content = File.read("file.txt")
lines = File.readlines("file.txt")
content = File.read("file.txt")
lines = File.readlines("file.txt")
Block-based reading (auto-closes)
基于块的读取(自动关闭)
File.open("file.txt") do |file|
file.each_line do |line|
puts line
end
end
File.open("file.txt") do |file|
file.each_line do |line|
puts line
end
end
Writing files
写入文件
File.write("output.txt", "Hello, World!")
File.open("output.txt", "w") do |file|
file.puts "Line 1"
file.puts "Line 2"
end
File.write("output.txt", "Hello, World!")
File.open("output.txt", "w") do |file|
file.puts "Line 1"
file.puts "Line 2"
end
File operations
文件操作
File.exist?("file.txt")
File.directory?("path")
File.size("file.txt")
File.mtime("file.txt") # Modification time
File.exist?("file.txt")
File.directory?("path")
File.size("file.txt")
File.mtime("file.txt") # 修改时间
Directory operations
目录操作
Dir.glob("**/*.rb") # Find all Ruby files recursively
Dir.foreach("path") { |file| puts file }
Dir.mkdir("new_dir")
undefinedDir.glob("**/*.rb") # 递归查找所有Ruby文件
Dir.foreach("path") { |file| puts file }
Dir.mkdir("new_dir")
undefinedRegular Expressions
正则表达式
ruby
undefinedruby
undefinedPattern matching
模式匹配
text = "Hello, my email is john@example.com"
text = "Hello, my email is john@example.com"
Match operator
匹配操作符
text =~ /\w+@\w+.\w+/ # => 18 (match position)
text =~ /\w+@\w+.\w+/ # => 18(匹配位置)
Match method
匹配方法
match = text.match(/(\w+)@(\w+).(\w+)/)
match[0] # => "john@example.com"
match[1] # => "john"
match[2] # => "example"
match = text.match(/(\w+)@(\w+).(\w+)/)
match[0] # => "john@example.com"
match[1] # => "john"
match[2] # => "example"
Named captures
命名捕获
match = text.match(/(?<user>\w+)@(?<domain>\w+).(?<tld>\w+)/)
match[:user] # => "john"
match[:domain] # => "example"
match = text.match(/(?<user>\w+)@(?<domain>\w+).(?<tld>\w+)/)
match[:user] # => "john"
match[:domain] # => "example"
Scan for all matches
扫描所有匹配项
emails = text.scan(/\w+@\w+.\w+/)
emails = text.scan(/\w+@\w+.\w+/)
Replace with regex
使用正则替换
text.gsub(/\b\w{4}\b/, "****") # Mask 4-letter words
undefinedtext.gsub(/\b\w{4}\b/, "****") # 掩码4字母单词
undefinedTesting Ruby Code
Ruby代码测试
Minitest (Standard Library)
Minitest(标准库)
ruby
require 'minitest/autorun'
class UserTest < Minitest::Test
def setup
@user = User.new(name: "John", age: 30)
end
def test_adult_with_age_over_18
assert @user.adult?
end
def test_name_is_capitalized
assert_equal "John", @user.name
end
def test_invalid_age_raises_error
assert_raises(ArgumentError) do
User.new(name: "John", age: -5)
end
end
def teardown
# Cleanup if needed
end
endruby
require 'minitest/autorun'
class UserTest < Minitest::Test
def setup
@user = User.new(name: "John", age: 30)
end
def test_adult_with_age_over_18
assert @user.adult?
end
def test_name_is_capitalized
assert_equal "John", @user.name
end
def test_invalid_age_raises_error
assert_raises(ArgumentError) do
User.new(name: "John", age: -5)
end
end
def teardown
# 如有需要进行清理
end
endRSpec (Popular Testing Framework)
RSpec(流行的测试框架)
ruby
require 'rspec'
RSpec.describe User do
let(:user) { User.new(name: "John", age: 30) }
describe '#adult?' do
context 'when age is over 18' do
it 'returns true' do
expect(user.adult?).to be true
end
end
context 'when age is under 18' do
let(:user) { User.new(name: "Jane", age: 15) }
it 'returns false' do
expect(user.adult?).to be false
end
end
end
describe '#initialize' do
it 'raises error for negative age' do
expect { User.new(name: "John", age: -5) }
.to raise_error(ArgumentError, /negative age/)
end
end
describe '#name' do
it 'returns capitalized name' do
expect(user.name).to eq("John")
end
end
endruby
require 'rspec'
RSpec.describe User do
let(:user) { User.new(name: "John", age: 30) }
describe '#adult?' do
context 'when age is over 18' do
it 'returns true' do
expect(user.adult?).to be true
end
end
context 'when age is under 18' do
let(:user) { User.new(name: "Jane", age: 15) }
it 'returns false' do
expect(user.adult?).to be false
end
end
end
describe '#initialize' do
it 'raises error for negative age' do
expect { User.new(name: "John", age: -5) }
.to raise_error(ArgumentError, /negative age/)
end
end
describe '#name' do
it 'returns capitalized name' do
expect(user.name).to eq("John")
end
end
endTesting Best Practices
测试最佳实践
ruby
undefinedruby
undefined1. Use descriptive test names
1. 使用描述性的测试名称
def test_user_is_adult_when_age_is_over_18
Clear what is being tested
end
def test_user_is_adult_when_age_is_over_18
清晰表明测试内容
end
2. Arrange-Act-Assert pattern
2. Arrange-Act-Assert模式
def test_order_total
Arrange
order = Order.new
order.add_item(item: "Book", price: 10)
order.add_item(item: "Pen", price: 2)
Act
total = order.total
Assert
assert_equal 12, total
end
def test_order_total
准备(Arrange)
order = Order.new
order.add_item(item: "Book", price: 10)
order.add_item(item: "Pen", price: 2)
执行(Act)
total = order.total
断言(Assert)
assert_equal 12, total
end
3. Test one thing per test
3. 每个测试只测一件事
❌ Bad: Tests multiple things
❌ 不良实践:测试多个内容
def test_user
assert user.valid?
assert_equal "John", user.name
assert_equal 30, user.age
end
def test_user
assert user.valid?
assert_equal "John", user.name
assert_equal 30, user.age
end
✅ Good: Separate tests
✅ 良好实践:拆分测试
def test_user_is_valid
assert user.valid?
end
def test_user_name
assert_equal "John", user.name
end
def test_user_is_valid
assert user.valid?
end
def test_user_name
assert_equal "John", user.name
end
4. Use fixtures/factories for test data
4. 使用fixtures/factories生成测试数据
factories.rb
factories.rb
FactoryBot.define do
factory :user do
name { "John" }
age { 30 }
email { "john@example.com" }
end
end
FactoryBot.define do
factory :user do
name { "John" }
age { 30 }
email { "john@example.com" }
end
end
In tests
在测试中使用
user = create(:user)
user_attrs = attributes_for(:user)
undefineduser = create(:user)
user_attrs = attributes_for(:user)
undefinedCommon Ruby Patterns and Idioms
常见Ruby模式与惯用语法
Method Chaining (Fluent Interface)
方法链式调用(流畅接口)
ruby
class QueryBuilder
def initialize
@conditions = []
@order = nil
end
def where(condition)
@conditions << condition
self # Return self for chaining
end
def order(field)
@order = field
self
end
def to_sql
sql = "SELECT * FROM users"
sql += " WHERE #{@conditions.join(' AND ')}" unless @conditions.empty?
sql += " ORDER BY #{@order}" if @order
sql
end
endruby
class QueryBuilder
def initialize
@conditions = []
@order = nil
end
def where(condition)
@conditions << condition
self # 返回self以支持链式调用
end
def order(field)
@order = field
self
end
def to_sql
sql = "SELECT * FROM users"
sql += " WHERE #{@conditions.join(' AND ')}" unless @conditions.empty?
sql += " ORDER BY #{@order}" if @order
sql
end
endUsage
使用示例
query = QueryBuilder.new
.where("age > 18")
.where("active = true")
.order("name")
.to_sql
undefinedquery = QueryBuilder.new
.where("age > 18")
.where("active = true")
.order("name")
.to_sql
undefinedBuilder Pattern
构建器模式
ruby
class UserBuilder
def initialize
@user = User.new
end
def with_name(name)
@user.name = name
self
end
def with_email(email)
@user.email = email
self
end
def build
@user
end
endruby
class UserBuilder
def initialize
@user = User.new
end
def with_name(name)
@user.name = name
self
end
def with_email(email)
@user.email = email
self
end
def build
@user
end
endUsage
使用示例
user = UserBuilder.new
.with_name("John")
.with_email("john@example.com")
.build
undefineduser = UserBuilder.new
.with_name("John")
.with_email("john@example.com")
.build
undefinedNull Object Pattern
空对象模式
ruby
class NullUser
def name
"Guest"
end
def admin?
false
end
def logged_in?
false
end
end
class UserSession
def current_user
@current_user || NullUser.new
end
endruby
class NullUser
def name
"Guest"
end
def admin?
false
end
def logged_in?
false
end
end
class UserSession
def current_user
@current_user || NullUser.new
end
endUsage - no nil checks needed
使用示例 - 无需检查nil
session = UserSession.new
puts session.current_user.name # "Guest" instead of error
undefinedsession = UserSession.new
puts session.current_user.name # 输出"Guest"而非报错
undefinedStrategy Pattern
策略模式
ruby
undefinedruby
undefinedDefine strategies
定义策略
class CreditCardPayment
def process(amount)
# Credit card logic
end
end
class PayPalPayment
def process(amount)
# PayPal logic
end
end
class CreditCardPayment
def process(amount)
# 信用卡支付逻辑
end
end
class PayPalPayment
def process(amount)
# PayPal支付逻辑
end
end
Use strategy
使用策略
class Order
def initialize(payment_strategy)
@payment_strategy = payment_strategy
end
def checkout(amount)
@payment_strategy.process(amount)
end
end
class Order
def initialize(payment_strategy)
@payment_strategy = payment_strategy
end
def checkout(amount)
@payment_strategy.process(amount)
end
end
Usage
使用示例
order = Order.new(CreditCardPayment.new)
order.checkout(100)
undefinedorder = Order.new(CreditCardPayment.new)
order.checkout(100)
undefinedObserver Pattern
观察者模式
ruby
require 'observer'
class Order
include Observable
attr_reader :status
def status=(new_status)
@status = new_status
changed
notify_observers(self)
end
end
class Logger
def update(order)
puts "Order status changed to: #{order.status}"
end
end
class Emailer
def update(order)
puts "Sending email about: #{order.status}"
end
endruby
require 'observer'
class Order
include Observable
attr_reader :status
def status=(new_status)
@status = new_status
changed
notify_observers(self)
end
end
class Logger
def update(order)
puts "Order status changed to: #{order.status}"
end
end
class Emailer
def update(order)
puts "Sending email about: #{order.status}"
end
endUsage
使用示例
order = Order.new
order.add_observer(Logger.new)
order.add_observer(Emailer.new)
order.status = "shipped"
undefinedorder = Order.new
order.add_observer(Logger.new)
order.add_observer(Emailer.new)
order.status = "shipped"
undefinedRuby Code Style and Conventions
Ruby代码风格与规范
Naming Conventions
命名规范
ruby
undefinedruby
undefinedClasses and Modules: PascalCase
类与模块:PascalCase
class UserAccount
end
module PaymentProcessing
end
class UserAccount
end
module PaymentProcessing
end
Methods and Variables: snake_case
方法与变量:snake_case
def calculate_total_price
total_amount = 0
end
def calculate_total_price
total_amount = 0
end
Constants: SCREAMING_SNAKE_CASE
常量:SCREAMING_SNAKE_CASE
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30
Predicate methods: end with ?
判断方法:以?结尾
def valid?
errors.empty?
end
def admin?
role == 'admin'
end
def valid?
errors.empty?
end
def admin?
role == 'admin'
end
Dangerous methods: end with !
危险方法:以!结尾
def save! # Raises exception on failure
raise "Invalid" unless valid?
persist
end
def downcase! # Mutates the object
@value = @value.downcase
end
undefineddef save! # 失败时抛出异常
raise "Invalid" unless valid?
persist
end
def downcase! # 修改对象本身
@value = @value.downcase
end
undefinedCode Organization
代码组织
ruby
undefinedruby
undefinedClass organization
类的组织顺序
class User
1. Extend and include statements
extend SomeModule
include AnotherModule
2. Constants
MAX_NAME_LENGTH = 100
3. Attribute macros
attr_reader :id
attr_accessor :name
4. Class methods
def self.find(id)
# ...
end
5. Initialization
def initialize(name)
@name = name
end
6. Public instance methods
def full_name
"#{first_name} #{last_name}"
end
7. Protected methods
protected
def internal_helper
# ...
end
8. Private methods
private
def calculate_something
# ...
end
end
undefinedclass User
1. 扩展与包含语句
extend SomeModule
include AnotherModule
2. 常量
MAX_NAME_LENGTH = 100
3. 属性宏
attr_reader :id
attr_accessor :name
4. 类方法
def self.find(id)
# ...
end
5. 初始化方法
def initialize(name)
@name = name
end
6. 公共实例方法
def full_name
"#{first_name} #{last_name}"
end
7. 受保护方法
protected
def internal_helper
# ...
end
8. 私有方法
private
def calculate_something
# ...
end
end
undefinedRuby Style Guidelines
Ruby风格指南
ruby
undefinedruby
undefinedUse 2 spaces for indentation
使用2个空格缩进
def method_name
if condition
do_something
end
end
def method_name
if condition
do_something
end
end
Avoid ternary operators for multi-line
避免多行三元运算符
❌ Bad
❌ 不良实践
result = some_long_condition ?
long_true_value :
long_false_value
result = some_long_condition ?
long_true_value :
long_false_value
✅ Good
✅ 良好实践
result = if some_long_condition
long_true_value
else
long_false_value
end
result = if some_long_condition
long_true_value
else
long_false_value
end
Use %w for word arrays
使用%w定义单词数组
❌ Bad
❌ 不良实践
STATES = ['draft', 'published', 'archived']
STATES = ['draft', 'published', 'archived']
✅ Good
✅ 良好实践
STATES = %w[draft published archived]
STATES = %w[draft published archived]
Use symbols for hash keys
使用符号作为哈希键
❌ Bad (when strings aren't needed)
❌ 不良实践(不需要字符串时)
{ 'name' => 'John', 'age' => 30 }
{ 'name' => 'John', 'age' => 30 }
✅ Good
✅ 良好实践
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
Use guard clauses
使用守卫子句
❌ Bad
❌ 不良实践
def process(value)
if value
if value.valid?
# ... main logic
end
end
end
def process(value)
if value
if value.valid?
# ... 主逻辑
end
end
end
✅ Good
✅ 良好实践
def process(value)
return unless value
return unless value.valid?
... main logic
end
def process(value)
return unless value
return unless value.valid?
... 主逻辑
end
Avoid returning from ensure
避免在ensure中返回值
❌ Bad - return value is ignored
❌ 不良实践 - 返回值会被忽略
def bad_example
return 42
ensure
return 0 # This overrides!
end
def bad_example
return 42
ensure
return 0 # 这会覆盖之前的返回值!
end
✅ Good
✅ 良好实践
def good_example
result = 42
ensure
cleanup
end
undefineddef good_example
result = 42
ensure
cleanup
end
undefinedDebugging Ruby Code
Ruby代码调试
Using pry for Debugging
使用pry进行调试
ruby
require 'pry'
def complex_method(data)
result = transform(data)
binding.pry # Execution pauses here
result * 2
endruby
require 'pry'
def complex_method(data)
result = transform(data)
binding.pry # 执行在此处暂停
result * 2
endIn pry session:
在pry会话中:
- ls: List available methods
- ls: 列出可用方法
- show-method method_name: Show method source
- show-method method_name: 显示方法源码
- cd object: Enter object context
- cd object: 进入对象上下文
- whereami: Show context
- whereami: 显示当前上下文
- continue: Resume execution
- continue: 恢复执行
undefinedundefinedUsing ruby/debug (Ruby 3.1+)
使用ruby/debug(Ruby 3.1+)
ruby
require 'debug'
def calculate(x, y)
debugger # Execution pauses here
result = x + y
result
endruby
require 'debug'
def calculate(x, y)
debugger # 执行在此处暂停
result = x + y
result
endCommands:
命令:
- step: Step into
- step: 单步进入
- next: Step over
- next: 单步跳过
- continue: Resume
- continue: 恢复执行
- info: Show information
- info: 显示信息
- break: Set breakpoint
- break: 设置断点
undefinedundefinedLogging Best Practices
日志最佳实践
ruby
require 'logger'
logger = Logger.new(STDOUT)
logger.level = Logger::INFOruby
require 'logger'
logger = Logger.new(STDOUT)
logger.level = Logger::INFODifferent log levels
不同日志级别
logger.debug("Detailed debug information")
logger.info("Informational messages")
logger.warn("Warning messages")
logger.error("Error messages")
logger.fatal("Fatal errors")
logger.debug("Detailed debug information")
logger.info("Informational messages")
logger.warn("Warning messages")
logger.error("Error messages")
logger.fatal("Fatal errors")
Structured logging
结构化日志
logger.info("User logged in") do
{ user_id: 123, ip: "192.168.1.1" }
end
undefinedlogger.info("User logged in") do
{ user_id: 123, ip: "192.168.1.1" }
end
undefinedConcurrency and Threading
并发与线程
Thread Basics
线程基础
ruby
undefinedruby
undefinedCreate threads
创建线程
threads = 3.times.map do |i|
Thread.new(i) do |thread_num|
puts "Thread #{thread_num} starting"
sleep 1
puts "Thread #{thread_num} done"
end
end
threads = 3.times.map do |i|
Thread.new(i) do |thread_num|
puts "Thread #{thread_num} starting"
sleep 1
puts "Thread #{thread_num} done"
end
end
Wait for all threads
等待所有线程完成
threads.each(&:join)
threads.each(&:join)
Thread-local variables
线程局部变量
Thread.current[:user_id] = 123
Thread.current[:user_id] # => 123
undefinedThread.current[:user_id] = 123
Thread.current[:user_id] # => 123
undefinedThread Safety
线程安全
ruby
undefinedruby
undefined❌ Bad: Race condition
❌ 不良实践:竞态条件
class Counter
def initialize
@count = 0
end
def increment
@count += 1 # Not atomic!
end
end
class Counter
def initialize
@count = 0
end
def increment
@count += 1 # 非原子操作!
end
end
✅ Good: Thread-safe with mutex
✅ 良好实践:使用互斥锁保证线程安全
class Counter
def initialize
@count = 0
@mutex = Mutex.new
end
def increment
@mutex.synchronize do
@count += 1
end
end
end
class Counter
def initialize
@count = 0
@mutex = Mutex.new
end
def increment
@mutex.synchronize do
@count += 1
end
end
end
✅ Better: Use Concurrent::AtomicFixnum
✅ 更优方式:使用Concurrent::AtomicFixnum
require 'concurrent'
counter = Concurrent::AtomicFixnum.new(0)
counter.increment
undefinedrequire 'concurrent'
counter = Concurrent::AtomicFixnum.new(0)
counter.increment
undefinedRactors for Parallelism (Ruby 3.0+)
使用Ractors实现并行(Ruby 3.0+)
ruby
undefinedruby
undefinedTrue parallel execution
真正的并行执行
def parallel_map(array, &block)
ractors = array.map do |item|
Ractor.new(item, block) do |value, transform|
transform.call(value)
end
end
ractors.map(&:take)
end
def parallel_map(array, &block)
ractors = array.map do |item|
Ractor.new(item, block) do |value, transform|
transform.call(value)
end
end
ractors.map(&:take)
end
Usage
使用示例
results = parallel_map([1, 2, 3, 4]) { |n| n * 2 }
results = parallel_map([1, 2, 3, 4]) { |n| n * 2 }
=> [2, 4, 6, 8]
=> [2, 4, 6, 8]
undefinedundefinedMetaprogramming
元编程
method_missing
method_missing
ruby
class DynamicAccessor
def initialize(data)
@data = data
end
def method_missing(method, *args)
if @data.key?(method)
@data[method]
else
super
end
end
def respond_to_missing?(method, include_private = false)
@data.key?(method) || super
end
endruby
class DynamicAccessor
def initialize(data)
@data = data
end
def method_missing(method, *args)
if @data.key?(method)
@data[method]
else
super
end
end
def respond_to_missing?(method, include_private = false)
@data.key?(method) || super
end
endUsage
使用示例
obj = DynamicAccessor.new(name: "John", age: 30)
obj.name # => "John"
obj.age # => 30
undefinedobj = DynamicAccessor.new(name: "John", age: 30)
obj.name # => "John"
obj.age # => 30
undefineddefine_method
define_method
ruby
class Model
%w[name email age].each do |attr|
define_method(attr) do
instance_variable_get("@#{attr}")
end
define_method("#{attr}=") do |value|
instance_variable_set("@#{attr}", value)
end
end
endruby
class Model
%w[name email age].each do |attr|
define_method(attr) do
instance_variable_get("@#{attr}")
end
define_method("#{attr}=") do |value|
instance_variable_set("@#{attr}", value)
end
end
endCreates name, name=, email, email=, age, age= methods
生成name, name=, email, email=, age, age=方法
undefinedundefinedclass_eval and instance_eval
class_eval和instance_eval
ruby
undefinedruby
undefinedclass_eval: Evaluates in class context
class_eval: 在类上下文中执行
String.class_eval do
def shout
upcase + "!"
end
end
"hello".shout # => "HELLO!"
String.class_eval do
def shout
upcase + "!"
end
end
"hello".shout # => "HELLO!"
instance_eval: Evaluates in instance context
instance_eval: 在实例上下文中执行
str = "hello"
str.instance_eval do
def custom_method
"Custom: #{self}"
end
end
str.custom_method # => "Custom: hello"
undefinedstr = "hello"
str.instance_eval do
def custom_method
"Custom: #{self}"
end
end
str.custom_method # => "Custom: hello"
undefinedMemory and Performance Profiling
内存与性能分析
Benchmark Module
Benchmark模块
ruby
require 'benchmark'
n = 1_000_000
Benchmark.bm(20) do |x|
x.report("Array#each:") do
arr = []
n.times { |i| arr << i }
end
x.report("Array#map:") do
(0...n).map { |i| i }
end
x.report("Array.new:") do
Array.new(n) { |i| i }
end
endruby
require 'benchmark'
n = 1_000_000
Benchmark.bm(20) do |x|
x.report("Array#each:") do
arr = []
n.times { |i| arr << i }
end
x.report("Array#map:") do
(0...n).map { |i| i }
end
x.report("Array.new:") do
Array.new(n) { |i| i }
end
endMemory Profiler
内存分析器
ruby
require 'memory_profiler'
report = MemoryProfiler.report do
# Code to profile
1000.times { "string" + "concatenation" }
end
report.pretty_printruby
require 'memory_profiler'
report = MemoryProfiler.report do
# 要分析的代码
1000.times { "string" + "concatenation" }
end
report.pretty_printRuby Profiler
Ruby分析器
ruby
require 'ruby-prof'
result = RubyProf.profile do
# Code to profile
10_000.times { expensive_operation }
end
printer = RubyProf::FlatPrinter.new(result)
printer.print(STDOUT)ruby
require 'ruby-prof'
result = RubyProf.profile do
# 要分析的代码
10_000.times { expensive_operation }
end
printer = RubyProf::FlatPrinter.new(result)
printer.print(STDOUT)Common Pitfalls and How to Avoid Them
常见陷阱与规避方法
1. Modifying Collections During Iteration
1. 迭代时修改集合
ruby
undefinedruby
undefined❌ Bad: Modifies while iterating
❌ 不良实践:迭代时修改集合
array = [1, 2, 3, 4, 5]
array.each do |item|
array.delete(item) if item.even? # Unpredictable!
end
array = [1, 2, 3, 4, 5]
array.each do |item|
array.delete(item) if item.even? # 结果不可预测!
end
✅ Good: Use reject or delete_if
✅ 良好实践:使用reject或delete_if
array.reject! { |item| item.even? }
array.reject! { |item| item.even? }
Or
或
array.delete_if { |item| item.even? }
undefinedarray.delete_if { |item| item.even? }
undefined2. Unintended Global Variable Modification
2. 意外修改全局变量
ruby
undefinedruby
undefined❌ Bad: Global variable
❌ 不良实践:全局变量
$user_count = 0
$user_count = 0
✅ Good: Class or instance variable
✅ 良好实践:类变量或实例变量
class UserCounter
@count = 0
class << self
attr_accessor :count
end
end
undefinedclass UserCounter
@count = 0
class << self
attr_accessor :count
end
end
undefined3. String Concatenation in Loops
3. 循环中的字符串拼接
ruby
undefinedruby
undefined❌ Bad: Creates many string objects
❌ 不良实践:创建大量字符串对象
result = ""
1000.times { |i| result += "#{i} " }
result = ""
1000.times { |i| result += "#{i} " }
✅ Good: Use array join
✅ 良好实践:使用数组join
result = 1000.times.map { |i| "#{i} " }.join
result = 1000.times.map { |i| "#{i} " }.join
✅ Better: Use string builder
✅ 更优方式:使用字符串构建器
result = String.new
1000.times { |i| result << "#{i} " }
undefinedresult = String.new
1000.times { |i| result << "#{i} " }
undefined4. Forgetting to Return Values
4. 忘记返回值
ruby
undefinedruby
undefined❌ Bad: No explicit return
❌ 不良实践:无显式返回
def calculate
total = items.sum
Implicitly returns total, but unclear
end
def calculate
total = items.sum
隐式返回total,但不够清晰
end
✅ Good: Explicit return for clarity
✅ 良好实践:显式返回以提升清晰度
def calculate
total = items.sum
return total
end
def calculate
total = items.sum
return total
end
✅ Best: Last expression is return value
✅ 最佳实践:最后一个表达式即为返回值
def calculate
items.sum
end
undefineddef calculate
items.sum
end
undefinedFramework-Specific Guidance
框架专属指导
Rails-Specific Best Practices
Rails专属最佳实践
ruby
undefinedruby
undefinedUse scopes for reusable queries
使用作用域定义可复用查询
class User < ApplicationRecord
scope :active, -> { where(active: true) }
scope :recent, -> { where('created_at > ?', 1.week.ago) }
end
class User < ApplicationRecord
scope :active, -> { where(active: true) }
scope :recent, -> { where('created_at > ?', 1.week.ago) }
end
Use concerns for shared behavior
使用concerns共享行为
module Timestampable
extend ActiveSupport::Concern
included do
before_save :update_timestamp
end
def update_timestamp
self.updated_at = Time.current
end
end
module Timestampable
extend ActiveSupport::Concern
included do
before_save :update_timestamp
end
def update_timestamp
self.updated_at = Time.current
end
end
Use strong parameters
使用强参数
class UsersController < ApplicationController
def create
@user = User.new(user_params)
# ...
end
private
def user_params
params.require(:user).permit(:name, :email, :age)
end
end
class UsersController < ApplicationController
def create
@user = User.new(user_params)
# ...
end
private
def user_params
params.require(:user).permit(:name, :email, :age)
end
end
Eager loading to avoid N+1 queries
预加载避免N+1查询
❌ Bad: N+1 query
❌ 不良实践:N+1查询
users = User.all
users.each { |user| puts user.posts.count }
users = User.all
users.each { |user| puts user.posts.count }
✅ Good: Eager load
✅ 良好实践:预加载
users = User.includes(:posts).all
users.each { |user| puts user.posts.count }
undefinedusers = User.includes(:posts).all
users.each { |user| puts user.posts.count }
undefinedQuick Reference Commands
快速参考命令
bash
undefinedbash
undefinedRuby version
Ruby版本
ruby -v
ruby -v
Run Ruby file
运行Ruby文件
ruby script.rb
ruby script.rb
Interactive Ruby (IRB)
交互式Ruby(IRB)
irb
irb
Execute inline Ruby
执行单行Ruby代码
ruby -e "puts 'Hello, World!'"
ruby -e "puts 'Hello, World!'"
Check syntax without executing
检查语法不执行
ruby -c script.rb
ruby -c script.rb
Run with warnings
带警告运行
ruby -w script.rb
ruby -w script.rb
Install gem
安装gem
gem install gem_name
gem install gem_name
List installed gems
列出已安装的gem
gem list
gem list
Update gems
更新gem
gem update
gem update
Bundle install (Rails)
安装依赖(Rails)
bundle install
bundle install
Run tests
运行测试
ruby test/my_test.rb
rake test
rspec spec/
ruby test/my_test.rb
rake test
rspec spec/
Ruby documentation
Ruby文档
ri String#upcase
ri Array
ri String#upcase
ri Array
Generate documentation
生成文档
rdoc
yard doc
undefinedrdoc
yard doc
undefinedResources and Further Learning
资源与进阶学习
- Official Ruby Documentation: https://docs.ruby-lang.org
- Ruby Style Guide: https://rubystyle.guide
- Ruby Weekly Newsletter: https://rubyweekly.com
- The Ruby Toolbox: https://www.ruby-toolbox.com
- RubyGems: https://rubygems.org
- Ruby官方文档: https://docs.ruby-lang.org
- Ruby风格指南: https://rubystyle.guide
- Ruby周刊: https://rubyweekly.com
- Ruby工具库: https://www.ruby-toolbox.com
- RubyGems: https://rubygems.org
Summary
总结
Ruby is designed for developer happiness and productivity. When writing Ruby code:
- Write readable code - Code is read more than it's written
- Follow conventions - Consistency helps teams collaborate
- Test thoroughly - Tests give confidence in refactoring
- Handle errors explicitly - Fail fast and provide context
- Optimize when necessary - Profile before optimizing
- Embrace Ruby's features - Use blocks, modules, and metaprogramming appropriately
- Stay current - Ruby 3.x brings significant improvements
Remember: Ruby rewards simple, expressive code that clearly communicates intent.
Ruby的设计目标是提升开发者的幸福感与生产力。编写Ruby代码时:
- 编写易读代码 - 代码被阅读的次数远多于编写次数
- 遵循规范 - 一致性有助于团队协作
- 充分测试 - 测试为重构提供信心
- 显式处理错误 - 快速失败并提供上下文
- 必要时再优化 - 先分析再优化
- 拥抱Ruby特性 - 合理使用块、模块与元编程
- 保持更新 - Ruby 3.x带来了显著改进
请记住:Ruby推崇简洁、富有表现力且能清晰传达意图的代码。