跳过正文

第1篇:Rails 架构概览

·1003 字·5 分钟
xieweicong
作者
xieweicong

学习目标:理解 Rails 的整体架构、组件划分和设计理念

1. Rails 是什么?
#

Rails 不是一个单一的 gem,而是一个由多个独立但紧密协作的组件组成的 框架集合。每个组件都可以独立使用,但组合在一起时能提供完整的 Web 开发解决方案。

核心理念
#

Rails 遵循几个核心设计理念:

  1. 约定优于配置(Convention over Configuration)

    • 减少开发者需要做的决策
    • 提供合理的默认值
  2. 不要重复自己(Don’t Repeat Yourself, DRY)

    • 信息在系统中只有单一、明确的表示
    • 减少重复代码
  3. 模块化设计

    • 每个组件职责单一
    • 组件间低耦合

2. Rails 的目录结构
#

让我们先看看 Rails 源代码的顶层结构:

rails/
├── actioncable/        # WebSocket 框架
├── actionmailbox/      # 接收邮件处理
├── actionmailer/       # 发送邮件
├── actionpack/         # 路由和控制器
├── actiontext/         # 富文本编辑器
├── actionview/         # 视图模板
├── activejob/          # 后台任务队列
├── activemodel/        # 模型接口定义
├── activerecord/       # ORM 数据库访问
├── activestorage/      # 文件上传存储
├── activesupport/      # Ruby 核心扩展
├── railties/           # 框架粘合剂
├── guides/             # 官方文档
└── tools/              # 开发工具

每个目录都是一个独立的 gem,都有自己的:

  • lib/ - 源代码
  • test/ - 测试文件
  • *.gemspec - gem 规格文件
  • README - 文档

3. Rails 十大核心组件
#

3.1 ActiveSupport - 基础设施
#

位置activesupport/

作用:为 Ruby 核心类提供扩展,是其他所有组件的基础。

核心功能

  • Ruby 核心类扩展(String, Array, Hash 等)
  • 回调系统(Callbacks)
  • 关注点(Concerns)
  • 自动加载(Autoloading)
  • 缓存(Caching)
  • 时间处理(Time zones)
  • I18n 国际化

示例代码位置

# activesupport/lib/active_support.rb - 主入口
# activesupport/lib/active_support/core_ext/ - 核心扩展
# activesupport/lib/active_support/concern.rb - Concern 模块

为什么重要:ActiveSupport 提供了 Rails 所有其他组件依赖的基础工具。


3.2 ActiveModel - 模型接口
#

位置activemodel/

作用:定义模型对象的标准接口,无需数据库支持。

核心功能

  • 验证(Validations)
  • 回调(Callbacks)
  • 属性赋值
  • 序列化
  • 脏检查(Dirty tracking)
  • 类型转换

关键类

  • ActiveModel::Model - 让任何类表现得像 ActiveRecord
  • ActiveModel::Validations - 验证框架
  • ActiveModel::Attributes - 属性系统

代码示例

# 你可以在不使用数据库的情况下拥有模型功能
class Person
  include ActiveModel::Model

  attr_accessor :name, :age
  validates :name, presence: true
  validates :age, numericality: true
end

3.3 ActiveRecord - ORM 数据访问
#

位置activerecord/

作用:实现对象关系映射(ORM),是 Rails 的数据持久化层。

核心功能

  • 数据库抽象层
  • 查询接口(Query Interface)
  • 关联(Associations)
  • 迁移(Migrations)
  • 验证
  • 回调

关键类

  • ActiveRecord::Base - 所有模型的基类
  • ActiveRecord::Relation - 查询构建器
  • ActiveRecord::ConnectionAdapters - 数据库适配器

依赖关系

ActiveRecord
  ├── ActiveModel (使用其验证、回调等)
  └── ActiveSupport (使用其工具类)

源码入口activerecord/lib/active_record.rb


3.4 ActionPack - 请求处理
#

位置actionpack/

作用:处理 HTTP 请求,包含路由和控制器。

核心功能

  • 路由系统(Routing)
  • 控制器(Controllers)
  • HTTP 请求/响应处理
  • 会话管理
  • Cookie 处理
  • 中间件(Middleware)

主要模块

  • ActionDispatch - 路由和请求处理
  • ActionController - 控制器基类
  • AbstractController - 控制器抽象层

代码结构

actionpack/
├── lib/
│   ├── action_dispatch/     # 路由、中间件
│   ├── action_controller/   # 控制器
│   └── abstract_controller/ # 抽象控制器

3.5 ActionView - 视图渲染
#

位置actionview/

作用:处理视图模板的查找、编译和渲染。

核心功能

  • 模板渲染(ERB, Builder 等)
  • Helper 辅助方法
  • Partial 部分模板
  • Layout 布局
  • 表单构建器

关键类

  • ActionView::Base - 视图上下文
  • ActionView::Template - 模板抽象
  • ActionView::Renderer - 渲染引擎

3.6 ActionMailer - 邮件发送
#

位置actionmailer/

作用:发送邮件,API 类似控制器。

核心功能

  • 邮件模板
  • 多格式邮件(HTML/文本)
  • 附件处理
  • 异步发送

示例

class UserMailer < ApplicationMailer
  def welcome_email(user)
    @user = user
    mail(to: user.email, subject: 'Welcome')
  end
end

3.7 ActionMailbox - 邮件接收
#

位置actionmailbox/

作用:接收和处理入站邮件。

核心功能

  • 邮件路由
  • 邮件处理器(Mailbox)
  • 支持多种邮件服务(Sendgrid, Mailgun 等)

3.8 ActiveJob - 后台任务
#

位置activejob/

作用:统一的后台任务接口,支持多种队列后端。

核心功能

  • 任务定义
  • 任务队列
  • 延迟执行
  • 重试机制
  • 适配器模式(Sidekiq, Resque 等)

代码示例

class ProcessOrderJob < ApplicationJob
  queue_as :default

  def perform(order)
    # 处理订单
  end
end

3.9 ActionCable - WebSocket
#

位置actioncable/

作用:实时双向通信,WebSocket 集成。

核心功能

  • Connection 连接管理
  • Channel 频道
  • 订阅和广播
  • 适配器(Redis, PostgreSQL 等)

3.10 ActiveStorage - 文件存储
#

位置activestorage/

作用:文件上传和云存储集成。

核心功能

  • 文件附件
  • 云服务支持(S3, GCS, Azure)
  • 图片变体(缩略图等)
  • 直传支持

3.11 ActionText - 富文本
#

位置actiontext/

作用:富文本编辑器集成(基于 Trix)。

核心功能

  • 富文本内容存储
  • 编辑器集成
  • 附件处理

3.12 Railties - 框架核心
#

位置railties/

作用:Rails 框架的粘合剂,负责组装所有组件。

核心功能

  • 应用启动
  • 生成器(Generators)
  • Rake 任务
  • 控制台(Console)
  • 初始化系统

关键文件

4. 组件依赖关系
#

Rails 组件之间有清晰的依赖层次:

层级 1(基础层):
  ActiveSupport
    └─ Ruby 核心扩展、工具类

层级 2(模型层):
  ActiveModel ──> ActiveSupport
    └─ 模型接口定义

  ActiveRecord ──> ActiveModel ──> ActiveSupport
    └─ 数据库 ORM

层级 3(请求处理层):
  ActionPack ──> ActiveSupport
    ├─ ActionDispatch(路由)
    └─ ActionController(控制器)

  ActionView ──> ActionPack ──> ActiveSupport
    └─ 视图渲染

层级 4(功能扩展层):
  ActionMailer ──> ActionPack ──> ActiveSupport
  ActiveJob ──> ActiveSupport
  ActionCable ──> ActionPack ──> ActiveSupport
  ActiveStorage ──> ActiveRecord ──> ActiveSupport
  ActionText ──> ActiveRecord ──> ActiveStorage

层级 5(框架层):
  Railties ──> 所有组件
    └─ 组装和初始化

关键观察

  1. ActiveSupport 是基石:几乎所有组件都依赖它
  2. ActiveModel 和 ActiveRecord 独立于 Web 层:可以在非 Web 应用中使用
  3. ActionPack 是 Web 核心:路由和控制器是 Web 应用的基础
  4. Railties 负责组装:它知道如何将所有组件整合在一起

5. Rails 模块的加载
#

让我们看看 Rails 的主入口文件:

# railties/lib/rails.rb
module Rails
  extend ActiveSupport::Autoload
  extend ActiveSupport::Benchmarkable

  class << self
    @application = @app_class = nil

    attr_writer :application
    attr_accessor :app_class, :cache, :logger

    def application
      @application ||= (app_class.instance if app_class)
    end

    def root
      application && application.config.root
    end

    def env
      @_env ||= ActiveSupport::EnvironmentInquirer.new(
        ENV["RAILS_ENV"].presence ||
        ENV["RACK_ENV"].presence ||
        "development"
      )
    end
  end
end

关键点

  • Rails 是一个模块,不是类
  • 使用 ActiveSupport::Autoload 实现延迟加载
  • Rails.application 是单例,代表你的应用
  • Rails.env 返回当前环境(development/test/production)

6. Gem 的组织方式
#

每个 Rails 组件都是一个独立的 gem:

# rails.gemspec(元 gem)
Gem::Specification.new do |s|
  s.name        = "rails"
  s.version     = version

  # 依赖所有子组件
  s.add_dependency "activesupport", version
  s.add_dependency "actionpack",    version
  s.add_dependency "actionview",    version
  s.add_dependency "activemodel",   version
  s.add_dependency "activerecord",  version
  s.add_dependency "actionmailer",  version
  s.add_dependency "activejob",     version
  s.add_dependency "actioncable",   version
  s.add_dependency "activestorage", version
  s.add_dependency "actiontext",    version
  s.add_dependency "actionmailbox", version
  s.add_dependency "railties",      version
end

这意味着

  • 安装 gem install rails 会安装所有组件
  • 你可以单独使用某个组件,如 gem install activerecord
  • 每个组件有自己的版本号,但通常保持一致

7. 实战:探索源码
#

让我们动手探索一下:

练习 1:查看 ActiveSupport 扩展
#

# 进入 Rails 源码目录
cd activesupport/lib/active_support/core_ext

# 查看都扩展了哪些核心类
ls -la
# 你会看到:array/, hash/, string/, integer/ 等

打开一个扩展文件看看:

# activesupport/lib/active_support/core_ext/string/inflections.rb
class String
  def pluralize(count = nil, locale = :en)
    # 单数变复数
  end

  def singularize(locale = :en)
    # 复数变单数
  end

  def camelize(first_letter = :upper)
    # 转换为驼峰命名
  end
end

练习 2:跟踪 ActiveRecord::Base
#

# 在 rails console 中
User.ancestors
# => [User, ApplicationRecord, ActiveRecord::Base, ...]

# 查看 User 的祖先链
User.ancestors.take(10).each { |k| puts k }

练习 3:理解路由DSL
#

# config/routes.rb
Rails.application.routes.draw do
  resources :posts
end

# 这背后发生了什么?
# 1. Rails.application 是你的应用实例
# 2. routes 返回一个 ActionDispatch::Routing::RouteSet
# 3. draw 方法接收一个块
# 4. resources 是一个 DSL 方法,创建 7 个路由

8. 设计模式识别
#

Rails 源码中大量使用了经典设计模式:

8.1 模块混入(Mixin)
#

module ActiveModel::Validations
  extend ActiveSupport::Concern

  included do
    # 当被 include 时执行
  end

  def valid?
    # 验证逻辑
  end
end

8.2 适配器模式
#

# ActiveJob 支持多种队列后端
ActiveJob::Base.queue_adapter = :sidekiq  # 或 :resque, :delayed_job

8.3 单例模式
#

Rails.application  # 总是返回同一个实例

8.4 回调模式
#

class User < ApplicationRecord
  before_save :normalize_email
  after_create :send_welcome_email
end

8.5 策略模式
#

# ActiveStorage 支持多种存储服务
config.active_storage.service = :amazon  # 或 :google, :local

9. 阅读源码的技巧
#

技巧 1:从你熟悉的 API 入手
#

你知道 User.find(1) 的用法,那就从这里开始:

# 1. 找到 find 方法的定义
# activerecord/lib/active_record/core.rb
def find(*ids)
  # ...
end

# 2. 使用 method_source 查看
User.method(:find).source_location
# => ["activerecord/lib/active_record/core.rb", 200]

技巧 2:使用调试器
#

# 在源码中插入断点
require 'debug'
binding.break

# 或者使用 pry
require 'pry'
binding.pry

技巧 3:查看测试
#

测试是最好的文档:

# activerecord/test/cases/finder_test.rb
test "find by id" do
  assert_equal @first, Topic.find(1)
end

技巧 4:绘制类图
#

使用工具如 rails-erd 或手动绘制:

ActiveRecord::Base
  ├── ActiveRecord::Core
  ├── ActiveRecord::Persistence
  ├── ActiveRecord::FinderMethods
  ├── ActiveRecord::Associations
  └── ActiveModel::Validations

10. 本章总结
#

通过本章学习,你应该了解:

  1. Rails 是组件集合,不是单一框架
  2. 十大核心组件及其职责
  3. 依赖层次:ActiveSupport → ActiveModel → 其他组件
  4. 模块化设计:每个组件都是独立的 gem
  5. 设计模式:Mixin、适配器、回调等
  6. 阅读源码的方法:从熟悉的 API 入手,使用调试工具

11. 下一步
#

在下一篇 Rails 启动流程分析 中,我们将深入探讨:

  • rails new 创建了什么
  • rails server 如何启动应用
  • Railtie 和 Engine 的作用
  • 初始化器的执行顺序

12. 练习题
#

在继续下一章之前,尝试回答以下问题:

  1. ActiveSupport 为什么是所有组件的基础?它提供了哪些关键功能?
  2. ActiveModel 和 ActiveRecord 的关系是什么?为什么要分离?
  3. ActionPack 包含哪两个主要模块?它们分别负责什么?
  4. 为什么 Railties 被称为"粘合剂"?
  5. Rails 使用了哪些设计模式?各有什么作用?

提示:如果有疑问,可以回到相应章节重新阅读,或者直接查看源码。


下一篇Rails 启动流程分析

返回学习指南首页