RESTful JSON API需要与Ember一起使用的约定

Cod*_*oet 15 ember.js ember-data

在Ember 模型介绍中,提到:

如果没有任何配置,Ember Data可以通过RESTful JSON API加载和保存记录及其关系,前提是它遵循某些约定.

我开始尝试使用基于令牌的RESTful JSON API,乍一看它并不是严格的RESTful.几个例子:

  1. 身份验证实现为 GET /api/authenticate?email=a@b.com&password=pass
  2. 大多数API即使失败也会返回200的状态(响应头).返回的json包含附加字段success(boolean)和code(int),用于指示API是否失败或通过.
  3. 网址不是基于名词(模型).例如,典型的消息编辑操作(通常应该是对URL等的POST /api/message/1/edit)实现为GET /api/edit_message?id=1&text=new

所以,我想知道是否有人可以列出certain conventions文档中提到的内容.这可以帮助我理解我是否可以使用ember-data.

Sar*_*rus 48

简短的回答是EmberData可能不适合您的REST API,因为您的REST API实际上不是一个REST API(它不使用HTTP谓词,而是将操作嵌入到查询字符串中).

为什么Ember数据可能不适合你

虽然过去Ember Data项目的目标可能是支持API,例如您所描述的API,但最近,Ember Data开发人员明确表示他们不打算将Ember Data用于非 - 传统的API.例如,已经删除了旨在"弥合差距"并允许将Ember数据与非传统REST API一起使用的BasicAdapter.

这是Emberjs.com上的博客文章的实际引用和链接(值得一读):

"Ember Data现在将专注于成为Ember.js应用程序的最佳库,以便与一致的传统API进行通信." (http://emberjs.com/blog/2013/05/03/ember-data-progress-update.html)

根据该博客文章的建议,您应该查看以下可能更适合您情况的数据持久性库:

https://github.com/endlessinc/ember-restless

https://github.com/ebryn/ember-model

最后,你可以随时使用AJAX来完成它,就像Discourse人一样http://eviltrout.com/2013/03/23/ember-without-data.html

认证

据我所知,Ember Data不处理应用程序身份验证,我认为你在那里得到了你的例子.对于您的身份验证系统,您可以查看类似Ember.SimpleAuth(https://github.com/simplabs/ember-simple-auth)的内容,该内容具有高度可配置性,可以与您的身份验证机制配合使用(尽管它肯定需要编写自定义认证).

编写自定义Authenticator非常简单.

什么是Ember数据实际期望

如果您还没有看过,我建议您阅读此页面:http://emberjs.com/guides/models/the-rest-adapter/

Ember Data将使用HTTP Verbs来传达意图.因此,当您在其中一个模型上调用createRecord然后保存商店时,Ember Data将向您的REST API发出HTTP POST.当您尝试获取记录时,Ember将发出GET请求.当您尝试删除记录时,Ember将发出DELETE请求(等等).

假设您有三个模型,如下所示:

module.exports = App.ShoppingCart = DS.Model.extend({
    user: DS.belongsTo('user'), 
    items: DS.hasMany('item', {async:true}),
    name: attr('string'),
    enabled: attr('boolean')
});

module.exports = App.Item = DS.Model.extend({
    name: attr('string')
});

module.exports = App.User = DS.Model.extend({
   firstName: attr('string')
   lastName: attr('string')
});
Run Code Online (Sandbox Code Playgroud)

当您尝试使用this.store.find('shoppingCart', 1)Ember 加载记录时,将对模型名称的复数形式发出GET请求(在本例中GET /shoppingCarts/1).Ember有一堆内置规则来确定一个单词的复数形式,例如它知道复数searchsearches和不是searchs.一旦发出GET请求,您的REST API就需要返回以下JSON:

{
  "shoppingCart": {
      "id": 1,
      "name": "Bobs Shopping Cart",
      "user": 1, //this field links to the user with an id of 1
      "enabled": true,
      "items": [
        1,
        2
      ] 
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您正在执行此操作,this.store.find('shoppingCart')那么Ember Data将发出一个GET /shoppingCarts并期望返回一系列购物车对象,这些对象使用复数形式的模型名称键入.例如,像这样:

{
  "shoppingCarts": [
     {
       "id": 1, //not specified in the model but must be sent by the REST API
       "name": "Bob's Shopping Cart",
       "user": 1, //this field links to the user with an id of 1
       "enabled": true,
       "items": [
         1,
         2
       ] 
     },
     {
       "id": 2, 
       "name": "John's Shopping Cart",
       "user": 2, //this field links to the user with an id of 2
       "enabled": false,
       "items": [
         3,  // these are ids for the item models
         4
       ] 
     }
  ]
}
Run Code Online (Sandbox Code Playgroud)

请注意,从服务器返回记录时,需要包含id唯一标识要返回的记录的字段.ID字段未在模型中指定.当您创建新记录并将数据发送到服务器时,您不包含id字段(因为它将确定服务器端),但REST API将需要返回响应中id的内容.

在上面的示例中,如果Ember Data在商店中缓存了用户"1",那么它将只使用该信息,否则它将发出另一个GET请求GET /users/1以检索用户1的信息.(您可以通过sideloading使其更有效记录是否要避免多个GET请求).

总而言之,惯例是使用HTTP谓词来传达应采取的操作,Ember Data将发送请求的URL基于您要查询的模型名称的复数形式.

最大的警告

我上面写的大部分内容都是基于这样的假设:你想要"开箱即用"地使用Ember Data而不需要过多的定制.一般来说,我认为当您控制REST API时,Ember Data最容易使用,并且可以调整它以符合Ember Data对基于JSON的REST API如何工作的看法.可以更改Ember Data的默认行为,但是我对尝试弯曲Ember Data以适应我的API不是很有经验,因此您可能需要其他尝试执行此操作的人的输入.