我在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
答案 0 :(得分:12)
对外部服务(第三方)的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
LIB /
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
答案 1 :(得分:6)
这个很晚,但我想加上我的2p / 2c。
我喜欢尝试让我的控制器清除控制器代码以外的任何东西,我根据请求类型和参数将其松散地定义为程序流代码。例如,为请求类型选择正确的模板,或根据用户是否登录选择正确的方法进行调用。
在计算响应时,我不喜欢使用大量操作模型和设置实例参数的代码来丢弃控制器。这很难测试,甚至更难重复使用。我更喜欢推迟到另一个对象并将单个值对象返回到模板。
有时我可以推荐一个模型:也许它只是一个简单的查找,我只是将一个模型发送到模板或一组模型。
也许我已经在模型中实现了一个有用的方法来返回一个合适的值或值对象。
然而,有时我会做一些不使用模型的东西,或使用多个模型的东西,或者不觉得它实际上应该使模型混乱的东西。在这种情况下,控制器和模型都不是代码的适当位置。
lib目录也感觉不对。我倾向于将lib目录视为包含代码的地方,但我还没有把它变成宝石。如果我写的代码只在应用程序的上下文中有意义,那么它并不适合。
所以我转向服务对象。在“应用程序”下文件夹我有一个&#39;服务&#39;文件夹,其中包含封装单个网站行为块的小型功能类。 (或者有时,协调其他几项服务,为控制器提供简单的界面。)
这使我可以减少控制器和我的模型,并且可以放置需要联系API的代码。
如果你想更进一步,你可以将API本身包装在一个包装类(或一组类)中,并将它们保存在lib目录中(也许可以在以后的日期转换为gem)。然后,服务对象将执行调用具有适当值(从控制器传递)的API包装器的任务,并使用模板可以干净地查询的内容进行响应。
当然,您可以更进一步,添加更多图层。例如,表示层可以位于服务对象(提供通用值)和特定视图的格式数据之间。 (也许你想提供一个网页和一个RSS提要,例如他们需要不同的日期格式。)
但是你明白了。
答案 2 :(得分:4)
通过我的编码风格(以及对MVC的理解),外部调用将被放置在“无表格”模型中。 RailsCasts 193讨论了这个概念,Rails 4支持一种不那么笨重的语法。如果你需要对代码进行任何操作,那么模型似乎是放置这些代码的合理位置。将这些方法移动到控制器中会起作用,但随着应用程序的增长可能会产生问题。
外部API调用的另一个考虑因素实际上是将它们存储在数据库中,在那个时候肯定应该存在于模型中,因此(对我来说)它们在模型中应该更加清晰。