-
Rails Guides:Engine 可以看作为宿主应用提供附加功能的微型应用(如 feedmob-rescue, feedmob-sidebar)
-
而 Rails Application 实质上就是一个加强版的 Engine
- 解耦 (避免宿主应用代码过多,导致难以维护)
- 可以针对 engine 单独测试
- 虽然提供了 moutable 的方式可以使 engine 中的方法与宿主应用隔离开,不过需要注意的是,engine 中与 宿主应用相互调用方法时,需要加对方的前缀
# mounable
rails plugin new blorgh --mountable
# full
rails plugin new blorgh
通过 --moutable 选项生成的 engine. 会比 --full 选项增加如下特性【实质就是与宿主应用隔离开】
- 静态资源文件的清单文件(application.js 和 application.css)
- 具有独立命名空间的ApplicationController
- 具有独立命名空间的 ApplicationHelper
- 引擎的布局视图模板
- 在 config/routes.rb 文件中为引擎设置独立的命名空间:
# full
Rails.application.routes.draw do
end
# mountable
Blorgh::Engine.routes.draw do
end
- 在 lib/blorgh/engine.rb 文件中为引擎设置独立的命名空间:
# full
module Blorgh
class Engine < ::Rails::Engine
end
end
# mountable
module Blorgh
class Engine < ::Rails::Engine
isolate_namespace Blorgh
end
end
-
如果与宿主应用交互挺多,比如像
feedmob-rescue
这种直接从宿主应用捕获异常,新增中间件的处理请求异常的,或是功能简单,可以使用--full
-
担心会与宿主应用出现命名冲突,功能被覆盖掉,还是使用
--moutable
- 加载
lib/feedmob/sidebar/sidebar.rb
--> 引入engine | railtie
# lib/blorgh/engine.rb
module Blorgh
class Engine < ::Rails::Engine
# 这一行把 engine 与宿主应用的类隔离开,防止命名冲突
isolate_namespace Blorgh
end
end
这里的 isolate_namespace 方法尤其需要注意。通过调用此方法,可以把引擎的控制器、模型、路由和其他组件隔离到各自的命名空间中,以便和应用中的类似组件隔离开来。避免引擎中的组建被应用中的同名组件覆盖。
Feedmob::Rescue::Engine.routes.draw do
get :not_found, to: 'page#not_found'
end
- 这里的路由是通过 Blorgh::Engine 对象而非 YourApp::Application 类定义的。
- 这样做的目的是把引擎路由限制在引擎中,这样就可以根据需要把引擎路由挂载到不同位置,同时也把引擎路由和应用中的其他路由隔离开来。
-
full
Rails.application.routes.draw do
# ...
match "*path", to: "admin/advertisers#error_404", via: :all
end
full
选项不能通过挂载的方式灵活在宿主应用中插入 engine 路由的位置,默认就会出现在match "*path"
的后面导致出现地址访问不到的情况。
-
mountable
Rails.application.routes.draw do
# ...
mount Feedmob::Rescue::Engine, at: '/'
match "*path", to: "admin/advertisers#error_404", via: :all
end
moutable
选项可灵活插入到宿主应用的路由中,避免地址访问不到的情况
- 生成的 engine 路由如下:
not_found GET /not_found(.:format) feedmob/rescue/page#not_found
-
engine
中调用宿主
中的helper
# 错误
<%= link_to "Home", root_path %>
# 正确
<%= link_to "Home", main_app.root_path %>
-
宿主
应用中调用engine
的helper
-
mount Feedmob::Rescue::Engine, at: '/'
<%= link_to "Home",engine_path %>
-
mount Ahoy::Engine, at: '/ahoy'
<%= link_to "Home",ahoy.engine_path %>
- 例子:
feedmob-sidebar
module Feedmob
module Sidebar
class Engine < ::Rails::Engine
isolate_namespace Feedmob::Sidebar
initializer 'local_helper.action_controller' do
ActiveSupport.on_load(:action_view) do
include Feedmob::Sidebar::SidebarHelper
include Feedmob::Sidebar::PageRemarkHelper
end
end
end
end
end
- 作用:
ActiveSupport.on_load 可以延迟加载代码,在真正需要时才加载。
- 这里的作用就是在渲染页面(生成 ActionView 实例)的时候才会引入两个
Engine
中的helper
- Rails::Railtie is the core of the Rails framework and provides several hooks to extend Rails and/or modify the initialization process.
- 提供钩子来扩展 Rails 功能,通过在初始化中做一些定制化功能。
- 例子:
feedmob-rescue
->http_method_not_allowed
中间件
require 'feedmob/rescue/http_method_not_allowed'
module FeedmobRescue
class Railtie < Rails::Railtie
initializer "feedmob_rescue.configure_rails_initialization" do
if defined? ActionDispatch::RemoteIp
Rails.application.config.middleware.insert_after(ActionDispatch::RemoteIp, FeedmobRescue::HttpMethodNotAllowed)
else
Rails.application.config.middleware.use FeedmobRescue::HttpMethodNotAllowed
end
end
end
end