• 7.8 Models -- The Rest Adapter


    一、概述

    默认的,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:

    ActionHTTP VerbURL
    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中作为一个数组被再次发送。

  • 相关阅读:
    Android中使用File文件进行数据存储
    Android 获取 json
    Android服务之Service
    php
    宝塔数据库连接不上
    idea中使用github
    elasticjob 当当的分布式定时任务管理
    定时任务规则生成器
    MySQL中group_concat()函数的排序方法
    mysql 中关于怎么写 row_number()over(order by) 类似的功能支持
  • 原文地址:https://www.cnblogs.com/sunshineground/p/5165975.html
Copyright © 2020-2023  润新知