Не CRUD действия с ember-данными - PullRequest
12 голосов
/ 14 марта 2012

Допустим, у меня есть следующая модель данных ember:

App.Person = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName:  DS.attr('string'),
    starred:   DS.attr('boolean')
});

Это связано с приложением Rails со следующим довольно стандартным CRUD API:

GET    /people    - get a list of people
POST   /people    - create a new person
GET    /people/id - get a specific person
PUT    /people/id - update a specific person
DELETE /people/id - delete a specific person

Все это соответствует Ember-Данные со стандартным Store / Adapter.

Однако, допустим, что для того, чтобы «пометить» или «снять звезду» человека, API не позволяет нам сделать это стандартным действием обновления.Для этого действия есть определенная конечная точка API:

POST   /people/id/star   - mark a person as "starred"
POST   /people/id/unstar - mark a person as "unstarred"

Как мне совместить этот API с Ember Data?

Похоже, мне нужно расширить DS.Store и DS.RESTAdapter как-то, но я не уверен в том, что лучше всего сделать так, чтобы они знали об этих различных действиях.Также немного ошибочно то, что универсальный адаптер для приложения должен знать о людях, играющих главные роли.

Обратите внимание, что у меня нет контроля над API, поэтому я не могу POST /people/id знать о "главных ролях""чтобы оно соответствовало стандартному обновлению.

Ответы [ 5 ]

10 голосов
/ 13 апреля 2014

Прошло некоторое время, и это может быть невозможно в то время, но вы можете напрямую вызвать метод ajax вашего адаптера:

YourApp.Store.prototype.adapter.ajax(url, action, {data: hashOfParams})

Например:

YourApp.Store.prototype.adapter.ajax('/products', 'GET', {data: {ids: [1,2,3]}})

На ваш вопрос:

YourApp.Store.prototype.adapter.ajax('/people' + id + '/star','POST')

Редактировать - полезно использовать buildURL, особенно если вы установили пространство имен на вашем адаптере:

url = YourApp.Store.prototype.adapter.buildURL('people',id) + '/star'

Edit 2 - Вы также можете получить адаптер с помощью container.lookup('adapter:application'), что полезно, если у вас нет глобального доступа к приложению (например, модули ES6 / ember-cli)

Edit3 - Вышесказанное относится к устаревшей версии Ember / Ember-CLI.Теперь я определяю эту функцию в микшировании -

  customAjax: (method, type, id, action, hash = null) ->
    #note that you can now also get the adapter from the store -
    #adapter = @store.adapterFor('application')
    adapter = @container.lookup('adapter:application')
    url = adapter.buildURL(type, id) + '/' + action
    hash['data'] = $.extend({}, hash) if hash #because rails
    adapter.ajax(url, method, hash).then (result) =>
      return result

и называю ее так -

@customAjax('PUT', 'modelClass', modelId, 'nonCRUDActionName', optionalHashOfAdditionalData).then (response) =>
  #do something with response
2 голосов
/ 25 марта 2014

Я прошел через ту же проблему и решил ее, используя модифицированную версию, описанную здесь: Акции несырьевых рельсов в Ember.js

По сути, вам нужно использовать вызов Jquery AJAX, для меня важной частью было изменение contentType, чтобы данные аутентификации передавались в заголовках запроса, а не в данных формы (по умолчанию, если Вы включаете данные в свой звонок). Кроме того, убедитесь, что в AJAX-части задан правильный контекст, иначе «this» не будет работать в обратном вызове «success»:

App.ItemController = Ember.ObjectController.extend
    actions:
        starItem: ->
            controller = this
            item = @get 'model'
            id = item.id
            token = @auth.get 'authToken'
            $.ajax
                type: 'PUT'
                context: controller
                data: '{ "auth_token": "' + token + '"}'
                url: '/api/v1/items/' + id + '/star'
                contentType: 'application/json; charset=UTF-8'
                dataType: 'json'
                success: ->
                    if @get 'item.starred_by_user'
                        @set 'model.starred_by_user', false
                        item.decrementProperty('total_stars') 
                    else 
                        @set 'model.starred_by_user', true
                        item.incrementProperty('total_stars')
0 голосов
/ 18 марта 2012

В дискуссионной группе Иегуда упомянул, что это пока невозможно.

0 голосов
/ 15 марта 2013

Я думаю, что в CQRS термы star и unstar являются командами.Поэтому вы должны объявить модель PersonStar и работать с ней.

0 голосов
/ 14 марта 2012

Может быть, хорошее начало: https://github.com/beautifulnode/ember.request

Еще не пробовал, но в вашем случае кажется многообещающим ...

...