要求RESTful JSON API可用于Ember的约定 [英] Conventions required of RESTful JSON API to be usable with Ember

查看:86
本文介绍了要求RESTful JSON API可用于Ember的约定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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)和代码(int),表示API是否失败或通过。

  3. 网址不是基于名词(型号)的。例如,一般来说,像 / api / message / 1 / edit 这样的URL一般是POST的典型消息编辑操作被实现为GET / api / edit_message?id = 1& text = new

所以,我想知道有人可以列出这些某些约定是在文档中提到的。这可以帮助我理解我是否可以使用ember数据。

解决方案

简而言之,EmberData可能不是您的REST API非常适合您的REST API,因为它不是一个休息API(它不使用HTTP动词,而是将动作嵌入到查询字符串的一部分中)。



为什么Ember Data可能不适合您



虽然它可能曾经是过去Ember Data项目的一个目标,以支持您所描述的API,最近,Ember Data开发人员明确表示,他们不打算将Ember Data与非常规API一起使用。例如,旨在弥合差距并允许使用非常规REST API的Ember数据的BasicAdapter已被删除。



这是实际报价并链接到Emberjs.com的博文(值得一读):


Ember数据现在将专注于成为最好的库为
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,就像话语人 a href =http://eviltrout.com/2013/03/23/ember-without-data.html> http://eviltrout.com/2013/03/23/ember-without-data.html



验证



据我所知,Ember Data不处理应用程序认证,这是我认为你在那里得到的例子。对于您的身份验证系统,您可以查看Ember.SimpleAuth( https://github.com/simplabs/ember-simple- auth ),它是高度可配置的,并且应该使用您的身份验证机制(尽管它一定需要编写一个自定义的身份验证器)。



编写自定义身份验证器很漂亮



什么是Ember数据实际期望



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



Ember数据将使用HTTP动词传达意图。因此,当您在其中一个模型上调用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')
});

当您尝试使用 this.store.find(' shoppingCart',1) Ember将对模型名称(在这种情况下为 GET / shoppingCarts / 1 )的复数形式发出GET请求。 Ember有一系列规则来确定一个单词的复数形式,例如它知道搜索的复数是搜索而不是搜索。 GET请求完成后,您的REST API需要返回以下JSON:

  {
shoppingCart:{
id:1,
name:Bobs购物车,
user:1,//此字段链接到用户的ID为1
enabled:true,
items:[
1,
2
]
}
}

如果你正在做 this.store.find('shoppingCart')然后Ember数据将发出一个 GET / shoppingCarts ,并期望一个数字的购物车对象,键入与模型名称的复数形式。例如,如下所示:

  {
shoppingCarts:[
{
id:1,//未在模型中指定,但必须由REST API发送
name:Bob's Shopping Cart,
user:1,//此字段链接到ID为1
enabled的用户:true,
items:[
1,
2
]
},
{
id:2,
name:John's Shopping Cart,
user:2,//此字段链接到ID为2的用户
enabled:false,
items:[
3,//这些是项目模型的ids
4
]
}
]
}

请注意,当您从服务器返回记录时,您需要包括唯一标识要返回的记录的 id 字段。模型本身没有指定id字段。当您创建新记录并将数据发送到服务器时,不包括id字段(因为它将被确定为服务器端),但是REST API将需要返回该响应中的id。



在上面的例子中,如果Ember Data在用户存储中缓存了用户1,那么它只会使用该信息,否则将另外获得GET请求到 GET / users / 1 以检索用户1的信息(如果您想避免多个GET请求,可以通过侧面加载记录来提高效率)。总而言之,惯例是使用HTTP动词传达应采取的行动,Ember Data将根据复数形式发送请求的URL您要查询的型号名称。



大警告



我上面写的是基于你想要使用Ember Data开箱即用的假设,而不需要太多的定制。一般来说,我认为,当您控制REST API时,Ember Data最容易使用,并可根据Ember Data对基于JSON的REST API的工作原理进行调整。可以更改Ember Data的默认行为,但是我尝试将Ember Data弯曲成适合我的API,所以您可能需要一些尝试这样做的其他人的输入。


In the Ember Models Introduction, it is mentioned:

Without any configuration, Ember Data can load and save records and their relationships served via a RESTful JSON API, provided it follows certain conventions.

I'm getting started trying to use a token based, RESTful JSON API, which at first glance is not strictly RESTful. Few examples:

  1. Authentication is implemented as GET /api/authenticate?email=a@b.com&password=pass
  2. Most of the API's return Status of 200 (response header) even on failure. The returned json contains additional fields success (boolean) and code (int) which indicate if the API failed or passed.
  3. The urls are not based on nouns (models). For example, a typical message edit operation which should conventionally be a POST to a url like /api/message/1/edit is implemented as GET /api/edit_message?id=1&text=new

So, I was wondering if someone could list what these certain conventions are that are mentioned in the docs. This could help me understand if I could use ember-data or not.

解决方案

The short answer is that EmberData is probably not a good fit for your REST API as your REST API isn't really a rest API (it doesn't use HTTP verbs and instead embeds actions as part of the query string).

Why Ember Data Probably Isn't for You

While it may have been a goal of the Ember Data project in the past to support an API such as the one you are describing, more recently, the Ember Data developers have explicitly stated that they do not intend for Ember Data to be used with non-conventional APIs. For example, the BasicAdapter which was meant to "bridge the gap" and allow the use of Ember data with non-conventional REST APIs has been removed.

Here's the actual quote and link to the blog post at Emberjs.com (worth a read):

"Ember Data will now focus on being the best possible library for Ember.js apps to communicate with consistent, conventional APIs." (http://emberjs.com/blog/2013/05/03/ember-data-progress-update.html)

As recommended in that blog post you should check out the following data persistence libraries which might be better suited to your situation:

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

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

Finally, you can always do it yourself with AJAX much like the Discourse folks did http://eviltrout.com/2013/03/23/ember-without-data.html

Authentication

As far as I know Ember Data does not handle application authentication which is what I think you're getting at with your example there. For your authentication system you could look at something like Ember.SimpleAuth (https://github.com/simplabs/ember-simple-auth) which is highly configurable and should work with your authentication mechanism (although it will definitely require writing a custom Authenticator).

Writing a custom Authenticator is pretty straightforward.

What is Ember Data Actually Expecting

I'd recommend reading over this page if you haven't seen it yet: http://emberjs.com/guides/models/the-rest-adapter/

Ember Data is going to use HTTP Verbs to convey intent. So when you make a call to createRecord on one of your models and then save the store, Ember Data will issue an HTTP POST to your REST API. When you try to get a record, Ember will issue a GET request. When you try to delete a record Ember will issue a DELETE request (etc. etc.).

Lets say you have three models that looks like this:

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')
});

When you attempt to load a record using this.store.find('shoppingCart', 1) Ember will make a GET request to the pluralized form of the model name (in this case GET /shoppingCarts/1). Ember has a bunch of rules built in to determine the plural form of a word so for example it knows that the plural of search is searches and not searchs. Once the GET request is made your REST API needs to return the following 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
      ] 
    }
}

If you were doing this.store.find('shoppingCart') then Ember Data will issue a GET /shoppingCarts and expect back an array of shopping cart objects keyed with the plural form of the model name. For example, like this:

{
  "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
       ] 
     }
  ]
}

Note that when you return records from the server you need to include an id field which uniquely identifies the record being returned. The id field is not specified in the model itself. When you create a new record and send data to the server you don't include the id field (as it will be determined server side) but the REST API would then need to return what the id is in the response.

In the example above, if Ember Data has user "1" cached in the store then it will just use that information, otherwise it will make another GET request to to GET /users/1 to retrieve information for user 1. (You can make this more efficient by sideloading records if you want to avoid multiple GET requests).

To sum up, the convention is to use HTTP verbs to convey what action should be taken, the URL that Ember Data will send the request to is based on the pluralized form of the model name that you are querying.

The big caveat

Most of what I wrote above is based on the assumption that you want to use Ember Data "out of the box" without too much customization. Generally speaking I think Ember Data is easiest to work with when you have control over the REST API and can adjust it to conform to Ember Data's opinion of how a JSON based REST API should work. It is possible to change the default behavior of Ember Data but I'm not very experienced with trying to bend Ember Data to fit my API so you might need some input from someone else that has tried to do this.

这篇关于要求RESTful JSON API可用于Ember的约定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆