9

我在 Ruby on Rails 中有一个带有 mvc 框架的应用程序。截至目前,我在控制器中有 API 调用,但不认为这是适合他们的地方。我的所有 API 调用都应该放入什么样的文件?谢谢

def getDetails(id)
 api_response = HTTParty.get(base_uri, :query => {:DID => id, :DeveloperKey => devKey})
 @json_hash = api_response.parsed_response
 return @json_hash
end
4

3 回答 3

14

对外部服务(第 3 方)的 API 调用并不特定于您的应用,因为每个人都可以使用它们的服务(理论上)。据我了解,这些功能都在lib/目录中,因为它们不是特定于应用程序的。理想情况下,您可以从您lib的项目中提取代码,并将其放入lib/另一个项目中的其他人的代码中,它仍然可以正常工作。

把调用放在lib/. 如果需要,您可以根据控制器中返回的数据创建模型。

它看起来像这样:

应用程序/控制器/

class YourController < ApplicationController

  def getDetails
   # keep in mind, api call may fail so you may want surround this with a begin/rescue
   api_response = YourApiCall.new.get_details(params[:id])
   # perhaps create a model
   @model = SomeModel.new(fname: api_response[:first_name], lname: api_response[:last_name])
    # etc...
  end
end

库/

require 'HTTParty'

Class YourApiCall
  def get_details(id)
    HTTParty.get(base_uri, :query => {:DID => id, :DeveloperKey => devKey})
    @json_hash = api_response.parsed_response
    return @json_hash
  end
end
于 2013-03-04T16:40:47.620 回答
9

这个很晚了,但我想我会添加我的 2p/2c。

除了控制器代码之外,我喜欢尝试让我的控制器保持清洁,我根据请求类型和参数将其松散地定义为程序流代码。例如,为请求类型选择正确的模板或根据用户是否登录选择正确的调用方法。

在计算响应时,我不喜欢在控制器中乱扔大量操纵模型和设置实例参数的代码。这很难测试,甚至更难重复使用。我更喜欢推迟到另一个对象并将单个值对象返回给模板。

有时我可以遵循一个模型:也许这是一个简单的查找,我只是将一个模型发送到模板,或者一个模型数组。

也许我在模型中实现了一个有用的方法来返回适当的值或值对象。

然而,有时我正在做一些不使用模型的事情,或者使用多个模型,或者感觉它实际上不应该使模型混乱。在这种情况下,控制器和模型都不是代码的合适位置。

lib 目录也感觉不对。我倾向于将 lib 目录视为包含我还没有费心变成宝石的代码的地方。如果我正在编写的代码仅在应用程序的上下文中才有意义,那么它就不适合。

所以我转向服务对象。在“应用程序”文件夹下,我有一个“服务”文件夹,其中包含封装单个站点行为块的小型功能类。(或者有时,协调几个其他服务为控制器提供一个简单的接口。)

这让我可以精简我的控制器和模型,并为放置需要联系 API 的代码提供了一个完美的地方。

如果您想更进一步,您可以将 API 本身包装在一个包装类(或一组类)中,并将它们保存在 lib 目录中(以便以后转换为 gem)。然后,服务对象将执行使用适当的值(从控制器传递)调用 API 包装器的任务,并使用模板可以干净地询问的内容进行响应。

当然,您可以比这更进一步并添加更多层。例如,表示层可以位于服务对象(提供通用值)和特定视图的格式数据之间。(也许您想同时提供网页和 RSS 提要,例如,它们需要不同的日期格式。)

但你明白了。

于 2015-12-07T16:09:48.057 回答
5

根据我的编码风格(以及对 MVC 的理解),外部调用将被放置在“无表”模型中。RailsCasts 193谈到了这个概念,Rails 4 支持不那么笨重的语法。如果您需要对代码进行任何操作,模型似乎是放置这些的合乎逻辑的地方。将这些方法移到控制器中会起作用,但随着应用程序的增长可能会产生问题。

外部 API 调用的另一个考虑因素实际上是将它们存储在数据库中,那时它肯定应该在模型中,所以(对我来说)很清楚这些确实应该在模型中。

于 2013-03-04T16:24:56.763 回答