Rails 3.0 开始支持 Engine。设计 Engine 的初衷是将特定功能的 Rails 项目,打包为 Engine,分享给其他 Rail 项目使用。Engine 可以被看作是一个微型的应用程序,他提供一些额外的功能给他的宿主程序(host applications)。
Engine 分为两种:Full Engine 和 Mountable Engine。 通过以下命令,可以方便的创建 Engine。
rails plugin new engine_name --full # Full Engine rails plugin new engine_name --mountable # Mountable EnginePS:可以方便的将 Engine 打包为 Gem,从而在其他 Rails 项目中使用。
下面通过代码来学习这两种 Engine,并且对比两种实现所带来的利与弊,进行初步的分析。
以下实例,基于 Rails 3.2.3。基于 Rails 3.0 创建 Engine, 推荐安装 enginex Gem 来生成 Engine。 首先创建一个 Rails 项目:engine_demo
在 engine_demo 项目根目录下执行:
rails plugin new food --full
重新组织一下文件结构:将food 文件夹拷贝至 vendor 目录下 # 目录结构(截图)
Engine food 即是一个迷你版的 Rails application。 下面实现一个展示食物的页面。
# 新建一个 foods_controller.rb 包含 index 方法。 # food/app/controllers/foods_controller.rb class FoodsController < ActionController::Base def index end end # 配置路由 # food/config/routes.rb Rails.application.routes.draw do get "foods" => "foods#index" end # food/lib/food.rb require "food/engine" module Food end # food/lib/food/engine.rb module Food class Engine < Rails::Engine end end # engine_demoe Gemfile gem 'food', :path => "vendor/food" $ rake routes 》foods GET /foods(.:format) foods#index
特点: 没有命名空间,与 engine_demo 项目依赖度极高。 Engine food 通过修改 Rails 的 route,将其功能添加进engine_demo 项目。 优势: engine_demo 项目中不需要做额外的设置,即可拥有该功能。 Engine food 中的routes,controllers,models,helpers 直接开放给 engine_demo 使用。 劣势:容易引起命名冲突。
在 engine_demo 项目根目录下执行:
rails plugin new blog --mountable
Engine blog 的目录结构与 food 有些不一样。见下面的截图:
下面实现一个blog 展示页面。 看以下代码实例:
# blog/app/controllers/blog/application_controller.rb module Blog class ApplicationController < ActionController::Base end end # blog/lib/blog.rb require "blog/engine" module Blog end # blog/lib/blog/engine.rb module Blog class Engine < Rails::Engine isolate_namespace Blog end end # blog/app/controllers/blog/articles_controller.rb module Blog class ArticlesController < Blog:: ApplicationController def index end end end # blog/config/routes.rb Blog::Engine.routes.draw do get "articles" => "articles#index" end # engine_demo/Gemfile gem 'blog', :path => "vendor/blog" # engine_demo/config/routes.rb EngineDemo::Application.routes.draw do mount Blog::Engine => "/blog" end # engine_demo $ rake routes blog /blog Blog::Engine Routes for Blog::Engine: articles GET /articles(.:format) blog/articles#index
特点: 包含命名空间,很好的与 engine_demo 项目进行了隔离。 通过修改 engine_demo 的 route,引进 Engine blog 的功能。 优势:很好的控制了命名冲突的风险。 劣势:遵守命名规范,增加了一些配置。 总结:Engine 适合与对复杂应用进行划分的场景。
2012-08-29