一、概述

默认的,store将会使用 DS.RESTAdapter来加载和存储records。这个RESTAdapter假定URLS和JSON关联每一个model是约定好的;这意味着,如果你遵循这个规则,你将不需要配置这个adapter或者为了启动编写任何代码。

二、URL Conventions

1. 基于model的name,这个REST adapter足够的聪明来确定和它通信的URLS。例如,如果你通过一个ID请求一个Post

store.findRecord('post', 1).then(function(post) {
});

2. 这个REST适配器将会自动发送一个Get请求到/posts/1

3. 对于多个word名字,这个REST适配器将会使用lower_snake_case

4. 你可以采取的action,在REST适配器中,映射到下面的URL:

Action HTTP Verb URL
Find Record GET /posts/123
Find All GET /posts
Update PUT /posts/123
Create POST /posts
Delete DELETE /posts/123

5. Pluralization customization(多元化定制)

可以通过Ember.Inflector.inflector指定不规则的或者不可数的多元化:

var inflector = Ember.Inflector.inflector;

inflector.irregular('person', 'people');
inflector.uncountable('advice');

这将告诉这个REST适配器,对于person的请求应该去请求/people/1而不是/persons/1

6. Endpoint path customization(终端的路径定制)

通过设定在适配器中的namespace属性,终端的路径可以被加上一个命名空间前缀:

app/adapters/application.js

export default DS.RESTAdapter.extend({
namespace: 'api/1'
});

person的请求现在会导航到http://emberjs.com/api/1/people/1

7. Host customization(定制主机)

通过设定host属性,一个适配器可以导航到其他的hosts。

app/adapters/application.js

export default DS.RESTAdapter.extend({
host: 'https://api.example.com'
});

请求person现在将会导航到https://api.example.com/people/1

三、JSON Conventions

1. 当请求一条record,这个REST适配器期望你的服务器返回一个JSON代表这条record,它符合下列惯例。

2. JSON ROOT

(1) 返回的主要record应该在一个命名的根中。例如,如果你从/people/123请求一条record,响应应该被嵌套进一个被称为person的属性中:

{
"person": {
"firstName": "Jeff",
"lastName": "Atwood"
}
}

(2) 在destroyRecord之后或者在deleteRecord并且save之后,这个适配器期望服务器去返回一个空的对象({})。

(3) 如果你没有改变服务器返回的数据的选项,你可以重写这个DS.JSONSerializer#extractDeleteRecord,像这样:

extractDeleteRecord: function(store, type, payload) {
// If the payload is {delete: true}, Ember Data will try to set
// the new properties. Return null so it doesn't try to do that.
return null;
}

3. Attribute Names

(1) 属性名字应该用驼峰命名法。例如,如果你有一个model,像这样:

app/models/person.js

export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'), isPersonOfTheYear: DS.attr('boolean')
});

从服务器返回的JSON应该像这样:

{
"person": {
"firstName": "Barack",
"lastName": "Obama",
"isPersonOfTheYear": true
}
}

(2) 不规则的键可以被一个自定义的序列化器映射。如果person有一个名为lastNameOfPersonkey,并且期望的属性名字是简单的lastName,那么为这个model创建一个自定义的序列化器并且重写这个normalizeHash属性:

app/models/person.js

export default DS.Model.extend({
lastName: DS.attr('string')
});

app/serializers/person.js

export default DS.RESTSerializer.extend({
normalizeHash: {
lastNameOfPerson: function(hash) {
hash.lastName = hash.lastNameOfPerson;
delete hash.lastNameOfPerson; return hash;
}
}
});

4. Relationships

(1) 引用其他的rcords应该通过ID。例如,如果你有一个model,它有一个hasMany关系:

app/models/post.js

export default DS.Model.extend({
comments: DS.hasMany('comment', { async: true })
});

JSON应该编码这个关系为一个IDs数组:

{
"post": {
"comments": [1, 2, 3]
}
}

postComments可以通过post.get('comments')被加载。对每一个相关的comment这个REST适配器将会发送一个Get请求。

post.get('comments');

// GET /comments/1
// GET /comments/2
// GET /comments/3

(2) 你可以在你的适配器中通过设定coalesceFindRequests 为true阻止发送多个请求:

app/adapters/application.js

export default DS.RESTAdapter.extend({
coalesceFindRequests: true
});

这个REST适配器现在将会发送一个GET请求到/comments?ids[]=1&ids[]=2&ids[]=3

(3) 在JSON中任何belongsTo关系应该是Ember Data的模型名字的被驼峰化的版本。例如,如果你有一个model:

app/models/comment.js

export default DS.Model.extend({
post: DS.belongsTo('post')
});

这个JSON应该编码这个关系为一个到另一个record的ID:

{
"comment": {
"post": 1
}
}

(4) 如果需要这些命名约定可以被重写,通过实现keyForRelationship方法可以实现:

app/serializers/application.js

export default DS.RESTSerializer.extend({
keyForRelationship: function(key, relationship) {
return key + 'Ids';
}
});

5. Sideloaded Relationships

为了减少必要HTTP请求的数量,你可以在你的JSON响应中sideload额外的records。Sideloaded records存在于JSON root之外,并且被代表一个hash数组:

{
"post": {
"id": 1,
"title": "Node is not omakase",
"comments": [1, 2, 3]
}, "comments": [{
"id": 1,
"body": "But is it _lightweight_ omakase?"
},
{
"id": 2,
"body": "I for one welcome our new omakase overlords"
},
{
"id": 3,
"body": "Put me on the fast track to a delicious dinner"
}]
}

四、Creating custom transformations(创建自定义转化)

1. 在某些情况下,固有的属性类型string,number,booleandate可能会不够。例如,一个服务器可能返回一个不标准的日期格式。

2. Ember Data可以新注册一个JSON转换器作为属性:

app/transforms/coordinate-point.js

export default DS.Transform.extend({
serialize: function(value) {
return [value.get('x'), value.get('y')];
},
deserialize: function(value) {
return Ember.create({ x: value[0], y: value[1] });
}
});

app/models/cursor.js

export default DS.Model.extend({
position: DS.attr('coordinatePoint')
});

coordinatePoint从API中被接收的时候,它被期望是一个数组:

{
cursor: {
position: [4,9]
}
}

但是一旦加载到一个model实例,它将作为一个对象行为:

var cursor = this.store.findRecord('cursor', 1);
cursor.get('position.x'); //=> 4
cursor.get('position.y'); //=> 9

如果position被修改并且保存,在转换中它将通过serialize序列化函数并且在JSON中作为一个数组被再次发送。

7.8 Models -- The Rest Adapter的更多相关文章

  1. Android 自定义列表指示器

    在联系人界面 可以看到这种界面 手指快速滑动右边滑动条时 可以显示相应的字母图标 android里提供了android.widget.SectionIndexer这个接口去实现该效果 可是只能显示字母 ...

  2. How Network Load Balancing Technology Works--reference

    http://technet.microsoft.com/en-us/library/cc756878(v=ws.10).aspx In this section Network Load Balan ...

  3. Database and models

    Database and models The database Now that we have the Album module set up with controller action met ...

  4. 7.9 Models -- Connection to An HTTP Server

    一.概述 1. 如果你的Ember应用程序需要从一个HTTP服务器加载JSON数据,在你的服务器返回的任何格式中,配置Ember Data的过程将会加载records. 2. store使用一个被称为 ...

  5. 7.4 Models -- Pushing Records into the Store

    一.概述 1. store是作为一个所有records的缓存,这些records已经被你的应用程序加载.在你的app中如果你的路由或者一个controller请求一条record,如果它在缓存中这个s ...

  6. 7.1 Models -- Introduction

    一.概述 1. 模型是表示应用程序呈现给用户的底层数据的对象.不同的应用程序有不同的模型,这取决于它们正在试图解决什么问题. 2. 例如,一个照片共享应用程序可能有一个Phone模型来代表一个特殊的照 ...

  7. 7.2 Models -- Defining Models

    一.概述 1. 模型是一个类,它定义了你呈现给用户的数据的属性和行为.用户希望如果他们离开你的应用程序,并返回后(或如果他们刷新页面)看到的任何东西应该被一个model代表. 2. 确保在ember. ...

  8. Raspberry Pi - Huawei HiLink E3256 3G modem to ethernet adapter

    Raspberry Pi - Huawei HiLink E3256 3G modem to ethernet adapter This page documents how to configure ...

  9. 设计模式(七): 通过转接头来观察"适配器模式"(Adapter Pattern)

    在前面一篇博客中介绍了“命令模式”(Command Pattern),今天博客的主题是“适配器模式”(Adapter Pattern).适配器模式用处还是比较多的,如果你对“适配器模式”理解呢,那么自 ...

随机推荐

  1. google v8引擎常见问题

    最近在项目中使用v8来进行扩展,下面简单说一下使用v8过程中遇到的一些问题.   v8的多线程调用 最初调研v8的测试代码是单线程的,后来一个项目在多线程中使用,出现了一些问题,后来看到参考3中的才恍 ...

  2. Android.mk (1) 函数

    https://www.jianshu.com/p/46224d15fc5f 从函数说起 大家都习惯看从头,从构建目标讲起的,导致每篇文档熟的都是前面的部分.很多教程也都是想办法能够观其大略,从整体上 ...

  3. Building Boost for Android with error “cannot find -lrt”

    编辑tools/build/src/tools/gcc.jam rule setup-threading ( targets * : sources * : properties * ){ local ...

  4. 认识OpenStack中的flatnetwork

    目录 [隐藏] 1 Understanding FlatNetworking 1.1 FlatNetworking 1.1.1 Single Adapter, All in one setup 1.1 ...

  5. python实现简单购物车系统(练习)

    #!Anaconda/anaconda/python #coding: utf-8 #列表练习,实现简单购物车系统 product_lists = [('iphone',5000), ('comput ...

  6. javascript中top、clientTop、scrollTop、offsetTop的讲解(转载加总结)

    scrollHeight: 获取对象的滚动高度. scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离 scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最 ...

  7. 结对编程2—Fault&Error&Failure

    学习进度表 点滴成就 学习时间 新编写代码行数 博客量(篇) 学到知识点 第一周 8 0 0 了解软件工程 第二周 10 0 1 博文一篇 第三周 15 0 2 选择项目.调查问卷 第四周 20 80 ...

  8. 线性DP总结(LIS,LCS,LCIS,最长子段和)

    做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { ...

  9. CCCC L2-022. 重排链表

    题解:直接list模拟,头尾两个指针,分别将头尾元素push到另一个list里面,输处输入方式同上一篇 坑:第一发卡了第二个样例,第二发卡了第4个,莫名其妙,所以把两个代码合起来,然后强行ac了. # ...

  10. docker使用Dockerfile搭建spark集群

    1.创建Dockerfile文件,内容如下 # 基础镜像,包括jdk FROM openjdk:8u131-jre-alpine #作者 LABEL maintainer "tony@163 ...