Ruby脚本面试题整理:这些高频问题你得会

常见的ref="/tag/2028/" style="color:#2B406D;font-weight:bold;">Ruby基础题

面试官一上来可能不会直接问多复杂的东西,而是先看看你对语言的基本掌握情况。比如,问你 nilfalse 的区别。在 Ruby 里,只有 falsenil 是假值,其他都是真值,连空数组和空哈希都算真。

再比如,==equal?=== 的区别经常被拿来考。简单说,== 比较的是值,equal? 看的是对象是否完全一样(内存地址),而 === 常用于 case 语句中,比如正则匹配:

\/d+\/ === "123"  # => true
(1..5) === 3      # => true

块、yield 和 Proc 的使用

写 Ruby 不用块,那基本等于没写。面试时如果问到如何自定义一个支持块的方法,就得用 yield

def with_log
  puts "开始执行"
  yield
  puts "执行结束"
end

with_log { puts "我在干活" }
# 输出:
# 开始执行
# 我在干活
# 执行结束

如果想把块存起来以后用,就得靠 Proclambda。两者区别在于参数检查和 return 行为。lambda 对参数更严格,return 只退出自己;而 Proc 的 return 会从外层方法直接跳出。

类与模块的细节问题

Ruby 的模块不能实例化,但能被包含(include)或扩展(extend)。面试常问 include 和 extend 到底有啥不同。

简单说,include 把模块的方法变成实例方法,extend 把它变成类方法。举个例子:

module Greet
  def hello
    puts "你好"
  end
end

class Person
  include Greet
end

class Tool
  extend Greet
end

Person.new.hello  # => 你好
Tool.hello        # => 你好

常用方法的手动实现

有时候面试官会让你手写一个 map 方法,看看你对迭代的理解。

def my_map(array)
  result = []
  for item in array
    result << yield(item)
  end
  result
end

my_map([1, 2, 3]) { |x| x * 2 }  # => [2, 4, 6]

或者让你实现一个简单的 memoize 缓存机制,避免重复计算:

def memoize(&block)
  cache = {}
  lambda { |n|
    cache[n] ||= block.call(n)
  }
end

fib = memoize do |n|
  n <= 1 ? n : fib.(n-1) + fib.(n-2)
end

fib.(10)  # 快速返回 55

字符串处理实战题

有个经典题目是判断回文字符串。注意大小写和非字母数字字符的处理。

def palindrome?(str)
  cleaned = str.downcase.gsub(/[^a-z0-9]/, '')
  cleaned == cleaned.reverse
end

palindrome?("A man, a plan, a canal: Panama")  # => true

这种题看着简单,但边界处理容易出错,比如空格、标点、大小写混用的情况。

文件操作相关问题

Ruby 写脚本少不了和文件打交道。面试可能会让你读一个日志文件,统计某类错误出现的次数。

error_count = 0
File.foreach("app.log") do |line|
  error_count += 1 if line.include?("ERROR")
end
puts "发现 #{error_count} 个错误"

记得用 foreach 而不是 readlines,避免大文件撑爆内存。

实际项目中的小技巧

在真实工作中,经常需要处理配置文件。YAML 是 Ruby 里的常客。

require 'yaml'

config = YAML.load_file('config.yml')
puts config["database"]["host"]

如果 config.yml 长这样:

database:
  host: localhost
  port: 5432

这招在写自动化脚本时特别实用,比如部署前自动读取环境配置。