这个很晚了,但我想我会添加我的 2p/2c。
除了控制器代码之外,我喜欢尝试让我的控制器保持清洁,我根据请求类型和参数将其松散地定义为程序流代码。例如,为请求类型选择正确的模板或根据用户是否登录选择正确的调用方法。
在计算响应时,我不喜欢在控制器中乱扔大量操纵模型和设置实例参数的代码。这很难测试,甚至更难重复使用。我更喜欢推迟到另一个对象并将单个值对象返回给模板。
有时我可以遵循一个模型:也许这是一个简单的查找,我只是将一个模型发送到模板,或者一个模型数组。
也许我在模型中实现了一个有用的方法来返回适当的值或值对象。
然而,有时我正在做一些不使用模型的事情,或者使用多个模型,或者感觉它实际上不应该使模型混乱。在这种情况下,控制器和模型都不是代码的合适位置。
lib 目录也感觉不对。我倾向于将 lib 目录视为包含我还没有费心变成宝石的代码的地方。如果我正在编写的代码仅在应用程序的上下文中才有意义,那么它就不适合。
所以我转向服务对象。在“应用程序”文件夹下,我有一个“服务”文件夹,其中包含封装单个站点行为块的小型功能类。(或者有时,协调几个其他服务为控制器提供一个简单的接口。)
这让我可以精简我的控制器和模型,并为放置需要联系 API 的代码提供了一个完美的地方。
如果您想更进一步,您可以将 API 本身包装在一个包装类(或一组类)中,并将它们保存在 lib 目录中(以便以后转换为 gem)。然后,服务对象将执行使用适当的值(从控制器传递)调用 API 包装器的任务,并使用模板可以干净地询问的内容进行响应。
当然,您可以比这更进一步并添加更多层。例如,表示层可以位于服务对象(提供通用值)和特定视图的格式数据之间。(也许您想同时提供网页和 RSS 提要,例如,它们需要不同的日期格式。)
但你明白了。