在 Rails 4 中组织外部 API 调用 - 模块或 Class?

Organize External API Calls in Rails 4 - Module or Class?

我正在创建一个 Rails 应用程序,它将使用相当多的外部 API,例如 SalesForce、FolderGrid(如 Dropbox)等,它们都会同步到我的数据库。我从未使用过外部 api 调用,因此我创建了一些基本的 Ruby 脚本,其中包含分散的方法来测试对这些资源的调用。现在我想用我的完整 Rails 应用程序来实现它们。

到目前为止,我首先在我的 /lib 文件夹中创建一个目录来保存 api 调用 modules/classes..

/lib/apis/foldergrid.rb

现在我不确定组织代码的最佳方法是什么。在我的独立 Ruby 脚本中,我有 authenticating, creating a folder, auditing files, downloading files 等方法

模块中应该包含什么?我什至需要一个模块吗? class 中应该包含什么?我如何确保我可以在需要的地方在我的模型和控制器中使用这些方法?是否有关于外部 API 的最佳实践?

非常感谢任何资源、链接,and/or更深入的理解。

What should be in a Module?

模块应包含由不同 classes 共享的代码,或者可以将其添加到单个 class.

Do I even need a Module?

不,您可以通过继承实现相同的目的。如果没有代码可以分享,那么你可能不需要模块。

How do I make sure I can use these methods in my models and controllers where needed?

您可以在控制器中使用 class 访问它们:

SalesForceAPI.get_data

"Module or class?" 是 Ruby 以及任何其他支持这两种语言的古老问题。

我会将每个 API 的功能封装在 class 中。例如,您可以有一个 SalesForceAPI class。然后,如果您需要在 class 之间共享功能以进行身份​​验证、创建文件夹、审核文件或下载文件,您可以创建 API class.

每个需要访问 API class 的 classes 将从它继承:

SalesForceAPI < API

您可以通过创建一个 API 模块并将其混合到其他 class 中来实现相同的目的。在这种情况下,这主要是一个偏好问题,因为任何一种解决方案都很好。

FWIW,我不知道是否会有很多用于身份验证、创建文件夹、审核文件或下载文件的共享功能,因为每个 API 的工作方式可能完全不同。但是,如果它们是 REST API,那么您可以创建一些 REST 辅助方法并将它们放在 API class.

有关该主题的一个很好、易于理解且完整的资源是 Practical Object Oriented Design Ruby

我也有一个应用程序可以做到这一点(从多个 APIs 中提取数据)所以我可以告诉你我会做什么(或者在某些情况下,如果我要重新开始我现在会做什么).

数据存储

首先,如果您已经将从这些数据中提取的数据保存到 Rails 应用程序中,那么您将拥有代表数据本身的模型。所以这就是您在控制器中所指的内容,除非您的控制器负责调用 APIs。

尽可能使用 Gems

其次确保利用 APIs 现有的 gems,这样你就不会重新创建身份验证轮,解析 JSON 进出应用程序等。例如:有一个 rest-force gem for salesforce.

使用 Lib 中的 Ruby 个对象在模型和 API 响应之间进行映射

第三,我会让 类 将 API 响应和您的模型之间的数据映射到 "Plain old ruby objects" 并将它们存储在 lib/apis 文件夹中(不需要在这些情况下存储在模块中,但恕我直言)。它们最终可能会非常实用,在映射数据的情况下,这没问题。

APIs 不存在 Gems

在那些情况下,我肯定会将它们保存在模块下的一个或多个 类 中,在它们自己的 lib 文件夹中。这样你就可以在需要时将它们解析为 Gem(或者如果你花时间让它们成为 Gem 开始,我相信其他人会受益)。这周我自己才开始走这条路,使用 Infoconnect's API,它没有 Gem(或任何语言的任何代码示例)。但我并没有走得太远。

如果需要,为 V 和 C 之间的代码(视图和控制器)创建服务对象

如果您最终需要做任何事情来与用户交互以获得 API 信息或任何调用这些请求的东西,我会把它们放在 service objects 中,这样您的代码就不会得到在视图或控制器中膨胀。