42

我想知道是否有关于将非标准 Ruby 文件放在 Rails 应用程序中的位置的最佳实践,那些不适合任何默认目录(controllers/models​​ 等)的文件。

我说的是控制器/模型等使用的类,但不是任何 Rails 基类的子类。包含从模型中提取的功能的类,以减少它们的脂肪。其中一些看起来像模型但不是 AR 模型,其中一些看起来更像“服务”,有些介于两者之间或其他东西。

一些随机的例子:

  • 通过 facebook 等处理使用密码进行身份验证的“策略”类。
  • 封装参数的“XParams”对象或处理参数处理以执行一些复杂动作的“XCreator”对象,最终创建一些AR模型
  • 向外部 API 发出请求或封装这些请求和响应的类
  • 可以替代真实 AR 模型的假模型(例如访客用户)
  • Resque 职位
  • 从 Redis 存储和读取信息的类
  • 执行某些特定操作(如处理数据、生成报告等)并从 Resque 作业或 rake 任务中调用的类

我现在有很多这样的东西,其中一些被添加到lib其中最终成为一堆随机的类和模块,一些潜入app/models. 我想以某种方式组织这个,但我不知道从哪里开始。

只有AR模型才能进入app/models吗?或者也可以放任何域或辅助模型?您如何确定某物是否为模型?

所有不适合的东西都应该app进入lib吗?或者也许我应该添加一些新的自定义子目录app?哪些子目录,以及如何划分自定义类?

你如何在你的项目中处理这个问题?我知道每个项目都有点不同,但一定有一些相似之处。

4

5 回答 5

15

好问题 - 我没有具体的答案给你

但我建议查看这篇文章 - http://blog.codeclimate.com/blog/2012/02/07/what-c​​ode -goes-in-the-lib-directory / - 请务必阅读所有评论

在当前项目中,我在应用程序/模型下有大量非 ActiveRecord 对象,它可以工作但并不理想,我将“可重用”非应用程序特定代码放在 lib 下

我在辅助项目中尝试过的其他替代方案(比如我们有一堆命令对象)rails 对于应用程序下的命名空间来说很痛苦,默认情况下它会将所有内容加载到同一个命名空间中

app/
  commands/
    products/create_command.rb         # Products::CreateCommand
    products/update_price_command.rb   # Products::UpdatePriceCommand

备用,除了 src 或 app_name 目录下的 rails 之外的所有内容

app/
  src/
    commands/
      create_product.rb         # Commands::CreateProduct
      update_product_price.rb   # Commands::UpdateProductPrice

我还没有找到一个好的解决方案,理想情况下第二个更好,但最好不要在应用程序下有额外的目录,这样你就可以打开应用程序并查看控制器、命令、模型等......

于 2013-03-07T00:59:30.990 回答
9

您触及了许多不同的用例,我认为这部分是最接近“正确”答案的部分:

我现在有很多这样的东西,其中一些被添加到 lib 中,最终成为一堆随机的类和模块,一些潜入应用程序/模型中。我想以某种方式组织这个,但我不知道从哪里开始。

这在我的书中几乎是正确的。您没有提到的一件事是将各种碎片提取到单独的宝石中。与外部服务对话的类是提取的优秀候选者,如果策略类足够通用,它们也是如此。这些可以是私有的,因为运行您自己的 gem 服务器并不难,然后您显然可以在 ROR 应用程序中重用它们。

最后也是最具体的,resque 工作我塞进了 lib/jobs。

我的经验法则是,如果它是某种模型它会进入app/models. 如果不是,它可能属于lib或属于它的某个适当命名的子目录,例如lib/jobslib/extensionslib/external等。

于 2013-03-07T00:45:52.180 回答
3

我将任何模型类(如 STI 子类)放在apps/models. 我将其他课程放在 中lib,因为它似乎是放置它们的最佳位置。我很容易知道在哪里看。因为我的模型类都在一个地方,所以对我的测试进行分组也更容易。

按照惯例,我不愿意将辅助类放入app/models. 如果他们是演示者类,他们属于app/helpers. 如果他们不是,那么lib似乎对他们来说是最好的地方。

于 2013-03-07T00:44:43.263 回答
3

如果您有兴趣,我稍后还写了一篇关于此的后续文章,总结了我的发现:http ://blog.lunarlogic.io/2013/declutter-lib-directory/

于 2015-04-08T12:14:14.183 回答
1

我的类通常会进入lib子目录,其中与子目录同名的模块负责包含它们。(当涉及到自动加载器时,Rails 对文件名和类名非常敏感。)

另一种选择是将每个模块封装到自己的 gem 中,然后通过 Gemfile 引用 gem。这允许跨项目共享代码。

于 2013-03-07T00:45:42.707 回答