7.8 Models -- The Rest Adapter

1、概述html

默認的,store將會使用 DS.RESTAdapter來加載和存儲records。這個RESTAdapter假定URLS和JSON關聯每個model是約定好的;這意味着,若是你遵循這個規則,你將不須要配置這個adapter或者爲了啓動編寫任何代碼。api

2、URL Conventions數組

1. 基於model的name,這個REST adapter足夠的聰明來肯定和它通訊的URLS。例如,若是你經過一個ID請求一個Post服務器

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

2. 這個REST適配器將會自動發送一個Get請求到/posts/1app

3. 對於多個word名字,這個REST適配器將會使用lower_snake_caseasync

4. 你能夠採起的action,在REST適配器中,映射到下面的URL:ide

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指定不規則的或者不可數的多元化:post

var inflector = Ember.Inflector.inflector;

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

這將告訴這個REST適配器,對於person的請求應該去請求/people/1而不是/persons/1this

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

3、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"
  }]
}

4、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中做爲一個數組被再次發送。

相關文章
相關標籤/搜索