如何在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
相关产品推荐
相关产品推荐

