跳至内容 跳至搜索

Rails::Railtie 是 Rails 框架的核心,并提供了几个钩子来扩展 Rails 和/或修改初始化过程。

Rails 的每个主要组件(Action Mailer、Action Controller、Active Record 等)都实现了 railtie。每个组件都负责自己的初始化。这使得 Rails 本身没有任何组件钩子,从而允许使用其他组件来代替任何 Rails 默认组件。

开发 Rails 扩展不需要实现 railtie,但如果你需要在启动期间或启动后与 Rails 框架进行交互,那么就需要一个 railtie。

例如,执行以下任何操作的扩展将需要 railtie

  • 创建初始化器

  • 为应用程序配置 Rails 框架,例如设置生成器

  • 向环境添加 config.*

  • 使用 ActiveSupport::Notifications 设置订阅者

  • 添加 Rake 任务

创建 Railtie

要使用 railtie 扩展 Rails,请创建一个 Rails::Railtie 的子类。此类必须在 Rails 启动过程中加载,并且通常称为 MyNamespace::Railtie

以下示例演示了一个可与 Rails 一起使用或不使用的扩展。

# lib/my_gem/railtie.rb
module MyGem
  class Railtie < Rails::Railtie
  end
end

# lib/my_gem.rb
require "my_gem/railtie" if defined?(Rails::Railtie)

初始化器

要从 railtie 向 Rails 启动过程添加初始化步骤,只需使用 initializer 宏定义初始化代码

class MyRailtie < Rails::Railtie
  initializer "my_railtie.configure_rails_initialization" do
    # some initialization behavior
  end
end

如果指定了,该块还可以接收应用程序对象,以防你需要访问一些应用程序特定的配置,例如中间件

class MyRailtie < Rails::Railtie
  initializer "my_railtie.configure_rails_initialization" do |app|
    app.middleware.use MyRailtie::Middleware
  end
end

最后,你还可以将 :before:after 作为选项传递给 initializer,以防你想将其与初始化过程中的特定步骤耦合。

配置

Railtie 可以访问一个 config 对象,其中包含所有 railtie 和应用程序共享的配置

class MyRailtie < Rails::Railtie
  # Customize the ORM
  config.app_generators.orm :my_railtie_orm

  # Add a to_prepare block which is executed once in production
  # and before each request in development.
  config.to_prepare do
    MyRailtie.setup!
  end
end

加载 Rake 任务和 生成器

如果您的 railtie 具有 Rake 任务,您可以通过 rake_tasks 方法告知 Rails 加载它们

class MyRailtie < Rails::Railtie
  rake_tasks do
    load "path/to/my_railtie.tasks"
  end
end

默认情况下,Rails 从您的加载路径加载生成器。但是,如果您想将生成器放置在其他位置,可以在 railtie 中指定一个块,该块将在常规生成器查找过程中加载它们

class MyRailtie < Rails::Railtie
  generators do
    require "path/to/my_railtie_generator"
  end
end

由于加载路径上的文件名在 gem 之间共享,因此请确保通过 railtie 加载的文件具有唯一名称。

在 Rails 服务器启动时运行另一个程序

在开发中,通常需要在 Rails Server 旁边运行另一个进程。例如,您可能希望启动 Webpack 或 React 服务器。或者,您可能需要运行作业调度程序进程,如 Sidekiq。这通常是通过打开一个新 shell 并从此处运行程序来完成的。

Rails 允许您指定一个 server 块,该块将在 Rails 服务器启动时被调用。这样,您的用户就不必记住打开一个新 shell 并运行另一个程序,这使得每个人都更不容易混淆。它可以像这样使用

class MyRailtie < Rails::Railtie
  server do
    WebpackServer.start
  end
end

ApplicationEngine

引擎只不过是一个已设置了一些初始化程序的 railtie。并且由于 Rails::Application 是一个引擎,因此此处描述的相同配置可以在两者中使用。

请务必查看这些特定类的文档以获取更多信息。

命名空间
方法
A
C
G
I
R
S
包含的模块

常量

ABSTRACT_RAILTIES = %w(Rails::Railtie Rails::Engine Rails::Application)
 

属性

[R] load_index

类公共方法

abstract_railtie?()

# File railties/lib/rails/railtie.rb, line 172
def abstract_railtie?
  ABSTRACT_RAILTIES.include?(name)
end

configure(&block)

允许您配置 railtie。这是在 Railtie::Configurable 中看到的相同方法,但此模块不再是 Railtie 的所有子类的必需项,因此我们在此提供类方法。

# File railties/lib/rails/railtie.rb, line 190
def configure(&block)
  instance.configure(&block)
end

console(&blk)

# File railties/lib/rails/railtie.rb, line 156
def console(&blk)
  register_block_for(:load_console, &blk)
end

generators(&blk)

# File railties/lib/rails/railtie.rb, line 164
def generators(&blk)
  register_block_for(:generators, &blk)
end

inherited(subclass)

# File railties/lib/rails/railtie.rb, line 198
def inherited(subclass)
  subclass.increment_load_index
  super
end

instance()

由于 Rails::Railtie 无法实例化,因此调用 instance 的任何方法都只打算在 Railtie 的子类上调用。

# File railties/lib/rails/railtie.rb, line 183
def instance
  @instance ||= new
end

railtie_name(name = nil)

# File railties/lib/rails/railtie.rb, line 176
def railtie_name(name = nil)
  @railtie_name = name.to_s if name
  @railtie_name ||= generate_railtie_name(self.name)
end

rake_tasks(&blk)

# File railties/lib/rails/railtie.rb, line 152
def rake_tasks(&blk)
  register_block_for(:rake_tasks, &blk)
end

runner(&blk)

# File railties/lib/rails/railtie.rb, line 160
def runner(&blk)
  register_block_for(:runner, &blk)
end

server(&blk)

# File railties/lib/rails/railtie.rb, line 168
def server(&blk)
  register_block_for(:server, &blk)
end

subclasses()

# File railties/lib/rails/railtie.rb, line 148
def subclasses
  super.reject(&:abstract_railtie?).sort
end

类受保护的方法

increment_load_index()

# File railties/lib/rails/railtie.rb, line 206
def increment_load_index
  @@load_counter ||= 0
  @load_index = (@@load_counter += 1)
end

实例公共方法

config()

用于在 Railties 上创建 config 对象,即 Railtie::Configuration 的一个实例,由 Railties 和 Application 用于存储相关配置。

# File railties/lib/rails/railtie.rb, line 263
def config
  @config ||= Railtie::Configuration.new
end