我只是一个Rails的使用者,很多的事情了解得并不深,视角和深度都有限,发这个帖子除了提出自己的疑问,更主要是希望听听大家意见,分享大家的心得。
engine被加入rails core曾经是一件很令我开心的事情,尤其是当我需要把一些固定的独立的MVC逻辑写成gem或者plugin的时候,原先大量的hack工作都消弭于无形。但是现在,我个人是觉得现在这个engine有点过了。
首先,作这个事情的目的有点过了,负责重构engine部分的Piotr Sarnacki坦言说作3.1里的这个重构的初始目标是mountable application,让一个process运行多个application, 比如说一个论坛,一个eshop可以打包作成一个gem或者类似的什么,需要的时候放进Gemfile就行。后来在同Carl和José讨论后决定作成mountable engine是一个近期更为可行的思路。实话实说,我很想知道为什么会想要让一个process运行多个application,分开运行有什么不好吗?包在一起不是把一大堆原本不需要rails实例关心的事情拉进rails了吗?
然后,手段也有点过了。举个例子,很多童鞋估计都看过这个
Mountable apps tutorial,为了能在plugin(or gem)下使用railtie里的generator,也为了测试需要,作者甚至直接加了一个假的rails project到生成的plugin里,而且把这个project放在生成的test/dummy文件夹(订证一点:也可以通过--dummy-path来制定位置)下。这本身就造成了很多混乱。首先这个rails实例并不只是test在用,rails这个命令也要用——生成的plugin里的script/rails直接就会去引用它,这是第一乱,test和development混成一团。然后,如果我不愿意用minitest测试,在创建plugin时加一个-T ,直接这个test文件夹就不会生成,这个dummy rails就不会存在,然后所有generator,所有作者引以为豪的类rails行为都无意义了。作者既然是参考enginex来作的这个plugin generator,为什么不看看enginex下大家为了测试engine plugin常用的diesel呢。
接着,在使用上也有点乱。举个例子,现在需要做一个投票功能的Gem,需要加一个migration。
好,现在有两种做法。
一个是把gem做成一个mountable engine,然后在gem下直接用rails g migration blabla生成migration ,然后在把这个Gem加入项目的Gemfile,再然后项目下就有一个rake命令(比如这个gem叫xyxy,命令就是rake xyxy:install:migrations),可以把这个migration拷到项目的db/migration文件夹内,并且自动解决掉migration序列号的问题。感觉还行,是吧?剔除这个功能本身的实现代码不看,是挺best practise的。
第二个是不把gem做成engine gem,就普通的一个lib文件夹,利用thor的一些方法做一个generator,给migration做一个template,用的时候把gem加入项目里的Gemfile,之后,直接在项目里rail g xyxy:migration,thor的方法也会自动解决序列号的问题。这个也挺干净利落,挺best practise的。
第一种做法用起来会很轻松,从头到尾就是几个现成的shortcut,两分钟完事了,而且几乎是个很坦然的无bug过程,但是生成的代码会有不少冗余,生成的mountable engine gem里有一堆你用不着但是不能删的文件夹;第二种做法要自己写一个generator,代码上很DRY,行行代码都是过脑子出来的,但也就意味着会有bug会花更多时间。
说这个例子与其说是提出问题,不如说是提出建议。engine除了mountable,是不是能做得更configurable,毕竟对绝大多数gem/plugin来说,只是需要对rails的一小部分进行扩展。写代码是很累的一个事情,我很喜欢shortcut,能不能只吃肉不挨打?
嗯...mountable engine里面的namespace和routes,建议有兴趣的朋友仔细实验过后再用,看起来不错,用起来也是pain in ass。