🐣 纯新手先看这一框(30 秒秒懂)
1
Ruby 适合做什么?Web 后端(Ruby on Rails)、脚本自动化、DevOps 工具、CLI。以「开发者幸福感」和开发效率著称。
2
为什么要学它?语法接近自然语言、表达力强。想快速做网站原型、或理解「约定优于配置」思想,Ruby 极佳。
3
怎么跑起来?本站「动手实验室」选 Ruby 点运行即可;本地装 Ruby,用 ruby hello.rb。
4
新手最常踩的坑?① 没有分号、靠换行;② 变量不用声明类型;③ nil 调用方法会 NoMethodError(类似空指针);④ 两个等号 == 比内容,三个 === 是 case 匹配。
1. Hello World没有分号,没有 main
puts "你好,Ruby!" # 打印并换行
print "1 + 2 = " # 不换行
puts 1 + 2
秒懂Ruby 脚本从上往下执行,不用包在 main 里,写完即运行。末尾分号可省略(推荐省略)。
2. 变量与一切皆对象连数字都是对象
变量不用声明类型,赋啥是啥。关键思想:一切皆对象——数字、字符串、类、nil 都能调用方法。
x = 3
puts x.class # Integer
puts 3.odd? # true(数字也是对象,能调方法)
name = "Ruby"
puts name.upcase # RUBY
干货
? 和 ! 是 Ruby 命名约定:返回布尔的方法常以 ? 结尾(empty?、nil?),会修改自身的方法常带 !(sort!)。3. 字符串与符号 Symbol命名的两种身份
"字符串":可变、每次出现可能新建对象。:符号:不可变、全局唯一(同名 Symbol 是同一个对象),用作名字/键。
s1 = "a"; s2 = "a"
puts s1.equal?(s2) # false(两个不同对象)
sym1 = :name; sym2 = :name
puts sym1.equal?(sym2) # true(同一个 Symbol)
易错点哈希键优先用
Symbol({name: "x"}),比字符串省内存且语义清晰;别在循环里狂建字符串当键。4. 数组与哈希Ruby 的集合很顺手
arr = [1, 2, 3]
arr << 4 # 追加,得到 [1,2,3,4]
h = { name: "Ruby", age: 30 }
puts h[:name] # Ruby(用 Symbol 作键)
puts arr.last # 4
5. 控制流if / unless / while
x = 10
puts "正数" if x > 0 # 后置 if(一行判断超好用)
unless x < 0 # unless = if not
puts "非负"
end
3.times { puts "循环" } # 块式循环
6. 方法 def用 def ... end 定义
def greet(name)
"你好,#{name}!" # 字符串插值 #{},最后一个表达式自动返回
end
puts greet("Ruby")
秒懂Ruby 方法「最后一个表达式的值」就是返回值,不用写
return(当然写也行)。7. 块 / Proc / LambdaRuby 的函数式灵魂
块({...} 或 do...end)是匿名代码块,可传给方法。区分:
block:最轻量,用yield调用,无对象身份。proc:return从外围方法返回。lambda:像「真正函数」,return只从自己返回,且严格检查参数个数。
def run
yield 3 # 调用传入的块
end
run { |n| puts "拿到 #{n}" }
lam = lambda { |a, b| a + b }
puts lam.call(2, 3)
8. 类与对象class / initialize / @实例变量
class Dog
def initialize(name)
@name = name # @ 开头是实例变量
end
def bark
"#{@name} 汪汪"
end
end
d = Dog.new("旺财")
puts d.bark
9. 模块与混入mixin 代替多继承
Ruby 单继承,用 module + include 把一组方法「混入」类,实现多能力复用。
module Greetable
def hi
"嗨,我是 #{@name}"
end
end
class Cat
include Greetable # 混入模块的方法
def initialize(name); @name = name; end
end
puts Cat.new("咪咪").hi
坑与秘
include 把模块方法作为实例方法混入;extend 则混入为类方法。这是 Rails 里各种「魔法」的基础。10. 异常处理begin / rescue / ensure
begin
puts 1 / 0
rescue ZeroDivisionError => e
puts "出错:#{e.message}"
ensure
puts "一定执行"
end
11. method_missing 元编程拦截未定义的方法调用
当对象收到未定义的方法,Ruby 会调 method_missing,借此能实现「动态方法名」。
class Dynamic
def method_missing(name, *args)
"你调用了 #{name},参数 #{args.inspect}"
end
end
d = Dynamic.new
puts d.whatever(1, 2) # 未定义方法也被接住
注意滥用
method_missing 会让代码难以追踪、性能下降。Rails 的 find_by_xxx 就是它的经典应用。12. 打开类与猴子补丁运行时修改已有类
Ruby 允许重新打开任何类(包括内置类)追加方法——强大也危险。
class String
def shout
self.upcase + "!"
end
end
puts "hello".shout # HELLO!
核心风险猴子补丁会影响全局,多个库改同一个方法会互相覆盖踩踏。生产代码慎用,务必加命名空间或 refinements 限定作用域。
13. 枚举 each / map / select函数式的日常
nums = [1, 2, 3, 4, 5]
puts nums.map { |n| n * n }.inspect # [1,4,9,16,25]
puts nums.select { |n| n.odd? }.inspect # [1,3,5]
puts nums.inject(0) { |s, n| s + n } # 15(累加)
14. 并发:GIL 与 RactorRuby 的并行真相
CRuby 有 全局解释器锁(GIL/GVL):同一时刻只有一个线程在执行 Ruby 代码。CPU 密集并行请用多进程;Ruby 3 的 Ractor 才提供真正的并行。
# 多线程适合 IO 等待,不适合 CPU 密集
threads = 3.times.map do
Thread.new { sleep 0.1; "done" }
end
puts threads.map(&:value).inspect
易错点以为开多线程就能加速计算是常见误区。GIL 下多线程主要帮你在等网络/磁盘时并发,CPU 密集还是单核跑。
15. 文件 IO读写的惯用写法
# 写
File.write("a.txt", "hello")
# 读
puts File.read("a.txt")
# 逐行
File.foreach("a.txt") { |line| puts line }
干货
File.write/read 一行搞定;foreach 惰性逐行读,处理大文件不占内存。16. attr_accessor 原理揭开属性方法的魔法
attr_accessor :x 等价于自动生成 def x; @x; end 和 def x=(v); @x=v; end。
class User
attr_accessor :name # 自动生成 getter + setter
end
u = User.new
u.name = "Ruby"
puts u.name
秒懂所谓「魔法」本质是元编程:用代码生成代码。
attr_reader/attr_writer/attr_accessor 只是帮你少写样板。🧪 动手实验室(点 ▶ 直接看结果)
代码已预填,打开自动跑一次;点 ▶ 运行 看结果,框内可直接改。
① Hello World
② 字符串与符号
③ 数组 map / select
④ 类与对象
⑤ 块与 yield
💡 连老师都不会教你的干货(工业级技巧)
1. 一切皆对象数字、类、nil 都响应方法。理解这点,
1.odd?、nil.nil? 就不奇怪了,也利于链式调用。2. 鸭子类型不检查「是什么类」,只关心「能响应什么方法」。用
respond_to?(:save) 判断能力而非类型。3. block/proc/lambda 区别lambda 严格参数个数、
return 只退出自身;proc 参数宽松、return 退出外围方法。混用会出诡异行为。4. 符号 vs 字符串Symbol 不可变且全局唯一,适合做键和名字;字符串可变适合内容。哈希键用
:sym 更省内存。5. 模块 mixin单继承下用
include/extend 混入能力,是 Ruby 复用代码的王道,也是 Rails 的基石。6. 猴子补丁风险打开类改全局会影响所有代码,多库冲突时互相覆盖。生产慎用,或限 scope 用 refinements。
7. method_missing拦截未定义方法实现动态 API(find_by_xxx),但拖慢方法查找、难调试,记得同时定义
respond_to_missing?。8. attr_accessor 原理本质是元编程生成 getter/setter,少写样板。需要只读/只写分别用
attr_reader/writer。9. 可变字符串与 frozenRuby 3 起字符串默认非冻结,但用
frozen_string_literal: true 魔法注释可让字面量冻结,省分配。10. 枚举链
each/map/select/inject 是日常主力,能替代大部分手写循环,代码更短更声明式。11. GIL 限制CRuby 全局锁下多线程只利于 IO 并发,CPU 密集仍单核。要真并行用多进程或 Ruby 3 的 Ractor。
12. 约定优于配置Rails 靠命名约定(如
User 类对应 users 表)省掉大量配置。学 Ruby 也建议顺手学这套思想。自测题(点击展开答案)
- Q1:Ruby 里
3.odd?能调用说明什么?A:说明一切皆对象——连整数都是对象,能响应方法。 - Q2:
:name和"name"作哈希键的区别?A:同名 Symbol 是同一个对象(equal?为 true),字符串每次新建。键应优先用 Symbol,省内存且唯一。 - Q3:
proc和lambda的return行为有何不同?A:lambda 的return只退出自身;proc 的return直接退出外围方法。参数检查也:lambda 严格、proc 宽松。 - Q4:Ruby 多线程能加速 CPU 密集计算吗?A:不能。CRuby 有 GIL,同刻只有一个线程跑 Ruby 代码;多线程主要帮 IO 并发。
- Q5:
attr_accessor :x做了什么?A:自动生成x的 getter 和x=的 setter,等价于手写两个方法。 - Q6:为什么猴子补丁危险?A:它修改全局类,多个库改同一方法会互相覆盖,导致难以追踪的 bug;生产应限定作用域。
- Q7:
inject(0) { |s,n| s+n }是干什么?A:累加(归约)。从初始值 0 开始,每次把元素 n 合并进累计值 s,最终得到总和。
本 Ruby 课程遵循 Ruby 3.x 常用子集,手机与电脑端自适应,配套本站运行器(Ruby)练习效果最佳。
公网参考:ruby-lang.org · ruby-doc.org · The Odin Project(Rails 入门)。