Rails Engine 算是 Rails 框架中的一项伟大发明,由于 Rails Application 本身也是 个 Engine, 因此它让你的 App 挂载其他 Engine, 甚至在 Engine 中挂载 Engine。它 的主要目标是可以模块化大型业务系统,例如做 Authentication 的 Devise, 做论坛的 Forem, 做电子商务的 Spree 等等。 Rails Engine 可以帮助将一个大型系统划分成多个小的独立的模块或业务,方便我们开发和后期维护。
因此,我们的 NICE 智能方案这边就考虑将方案的生成考虑做成了一个独立 Engine。 Rails Engine 很强大但其实也不算成熟,至少相对 Rails 来说算是。虽然大部分功能特性 跟 Rails Application 一样,但仍然会有些细节上的不同,而且这些不同就导致不能像在 Rails 中方便的去使用一些功能。下面就从几个方面来谈谈我在使用 Engine 过程中的一些经验。
gem
Rails Engine 中引用的 gems 不会被自动加载,你需要在 engine 使用它们之前手动把它们加载进来。 Rails 中有些 gem 之所以不需要 require 是因为这些 gem 里有 Railtie,Railtie 是 Rails 初始化 过程中很关键的部分,初始化过程找到所有包括 gems 中的 Railtie 并将其加载。但 Railtie 在 engine 中 就不起作用了,因为 engine 已经是一个 gem,在一个 gem 中使用另外个 gem 必须得先 require 它。 例如:
1 2 3 4 5 6 7 8 | |
Rspec
Engine 中使用 Rspec 可没那么直接,需要做一些手动配置。在生成 Engine 的时候得额外使用2个参数: -T –dummy-path=spec/dummy
-T跳过 test/unit--dummy-path设置 spec 和 dummy app 目录,默认是 test/dummy
在生成的 spec_helper.rb 中 require 一些测用的的 gem,如:
require 'capybara/rspec'
require 'database_cleaner'
再把
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
改成
ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')
Dir[File.join(ENGINE_RAILS_ROOT, "spec/support/**/*.rb")].each {|f| require f }
在 Engine 中配置 rspec 的 generators
1 2 3 4 5 6 7 | |
这样配置完后在 rails g 命令后才会自动生成对于的 spec 文件。
FactoryGirl
FactoryGirl 在 engine 中也是不能直接使用的,首先你需要在 spec_helper.rb 中添加
require 'factory_girl'
然后再添加
1 2 3 | |
来设置 factory 文件查找路径,在 engine 中他的默认的查找路径是在 spec/dummy/spec/factories 中, 所以必须的手动添加 spec/factories 路径进去。
autoload_paths
有时候你会需要添加额外的加载路径,如 app/services 目录,你可以在 Engine 中配置:
1 2 3 4 5 6 7 8 | |
assets & precompiling
有时候你需要加入一些只有 Engine 中会用到的一些资源文件,如 admin 后台管理中用的 admin.js 和 admin.css, 你可以将他们加入到 precompile 中:
1 2 3 4 5 6 7 | |
以上提到的都是 engine 和 rails 差异的地方,解决完所有问题后基本还是可以像 rails 中一样 正常工作的。





