You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails引擎MyGreatEngine中拆分导出API与静态文件路由?

拆分Rails引擎的API与静态路由方案

不用拆成两个引擎,也不用放弃前缀自定义,你可以在现有引擎内部把路由模块化,让宿主应用分别挂载不同的路由分支,具体操作如下:

1. 拆分引擎的路由文件

在你的mge gem里,把原来的config/routes.rb拆成两个独立文件:

  • config/routes/api.rb:专门放API相关路由
  • config/routes/static.rb:专门放静态文件相关路由

举个例子,api.rb可以这么写:

MyGreatEngine::Engine.routes.draw do
  namespace :api do
    resources :users, only: [:index, :show]
    # 其他API路由都放这
  end
end

static.rb的内容:

MyGreatEngine::Engine.routes.draw do
  get '/docs', to: 'static#docs'
  get '/assets/*path', to: 'static#serve'
  # 静态相关路由都放这
end

2. 在引擎中暴露可挂载的路由集合

打开引擎的核心文件lib/my_great_engine/engine.rb,添加两个类方法,用来返回对应的路由集合:

module MyGreatEngine
  class Engine < ::Rails::Engine
    isolate_namespace MyGreatEngine

    # 返回API路由集合
    def self.api_routes
      @api_routes ||= begin
        # 加载API路由文件
        Rails.application.routes.reloader.paths << File.expand_path("../../config/routes/api.rb", __FILE__)
        Rails.application.routes.reloader.reload!
        MyGreatEngine::Engine.routes
      end
    end

    # 返回静态路由集合
    def self.static_routes
      @static_routes ||= begin
        # 加载静态路由文件
        Rails.application.routes.reloader.paths << File.expand_path("../../config/routes/static.rb", __FILE__)
        Rails.application.routes.reloader.reload!
        MyGreatEngine::Engine.routes
      end
    end
  end
end

3. 宿主应用分别挂载路由

现在在宿主应用的config/routes.rb里,就能随意指定前缀挂载两类路由了:

# 把API路由挂到/api/v1/
mount MyGreatEngine::Engine.api_routes => '/api/v1'

# 把静态路由挂到/staticfiles/
mount MyGreatEngine::Engine.static_routes => '/staticfiles'

额外优化:允许宿主扩展路由

如果想让宿主应用能在引擎路由基础上追加自定义路由,可以改成块式定义:

# 引擎的engine.rb里修改
module MyGreatEngine
  class Engine < ::Rails::Engine
    isolate_namespace MyGreatEngine

    class << self
      def draw_api_routes(&block)
        routes.draw do
          namespace :api do
            # 引擎自带的API路由
            resources :posts
            # 允许宿主追加路由
            instance_eval(&block) if block_given?
          end
        end
      end

      def draw_static_routes(&block)
        routes.draw do
          # 引擎自带的静态路由
          get '/about', to: 'static#about'
          # 允许宿主追加路由
          instance_eval(&block) if block_given?
        end
      end
    end
  end
end

宿主应用里这么用:

# 先绘制引擎API路由,再追加自定义路由
MyGreatEngine::Engine.draw_api_routes do
  resources :comments
end
mount MyGreatEngine::Engine.routes => '/api/v1'

# 同理处理静态路由
MyGreatEngine::Engine.draw_static_routes do
  get '/custom-page', to: 'static#custom'
end
mount MyGreatEngine::Engine.routes => '/staticfiles'

这样既不用拆分引擎,也完全保留了前缀自定义的灵活性,所有共享逻辑都在同一个gem里维护,完美解决你的问题。

内容的提问来源于stack exchange,提问作者Spiros

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 11:02:25