2012-03-14 9 views
12

Decir que tengo el siguiente modelo brasa-datos:acciones no CRUD con brasa de datos

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

Este se comunica con una aplicación Rails con la siguiente API CRUD bastante estándar:

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 

Todo esto asigna a Ember-Data con el Store/Adapter estándar.

Sin embargo, digamos que para "destacar" o "desatar" a una persona, la API no nos permite hacer esto mediante la acción de actualización estándar. Hay un extremo de API específico para esta acción:

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

¿Cómo ajusto esta API con Ember Data?

Parece que tendría que ampliar DS.Store y DS.RESTAdapter de alguna manera, pero no estoy seguro de cuál es el mejor enfoque para que conozcan estas diferentes acciones. También se siente un poco mal que un Adaptador genérico para la aplicación tenga que estar al tanto de las personas protagonizadas.

Tenga en cuenta que no tengo control sobre la API, por lo que no puedo hacer que POST /people/id sea consciente de "protagonizar" para que coincida con una actualización estándar.

+0

Podría aceptar mi respuesta? El aceptado actualmente ya no es preciso – andorov

Respuesta

-1

En el grupo de discusión, Yehuda mencionado esto todavía no es posible.

+0

Saludos, pensé que podría ser el caso, ya que nada saltó en la fuente/pruebas. – rlivsey

+0

Esto ahora es posible - vea mi respuesta a continuación – andorov

0

Tal vez un buen comienzo: https://github.com/beautifulnode/ember.request

¿No tryed aún, pero parece prometedor en su caso ...

+0

Gracias, hay algunas opciones para la persistencia, pero actualmente estoy dando una oportunidad a Ember-Data, ya que supongo que será el predeterminado en el futuro. – rlivsey

+0

@rlivsey eventualmente encontraste una solución alternativa para usar acciones no crud con data-ember y hacer un post mental para respaldar tu solución aquí. Gracias – brg

+0

@mike Miré el código fuente de minutefavors que tiene una acción no crud y la ruta favorece la etiqueta # y en su ** [Apps.TagView] (https://github.com/mikecrittenden/minutefavors/blob/master /app/assets/javascripts/app/views/favors/tag.js)** definió una función url que devuelve '/ favor/tags'. Sé que usaste Ember-Recurso para esa aplicación, ¿cómo podemos hacer algo similar con ember-data restAdapter? Gracias, – brg

0

Creo que en CQRS therms star y unstar son comandos. Por lo tanto, debe declarar el modelo PersonStar y trabajar con él.

2

pasé por el mismo problema, y ​​lo resolvió usando una versión modificada de lo que se explica aquí: Non-crud rails actions in Ember.js

Básicamente, es necesario utilizar una llamada jQuery AJAX, la parte importante para mí era cambiar el contentType para que los datos de autenticación se envíen en los encabezados de solicitud, en lugar de en los datos de formulario (el valor predeterminado, si incluye datos en su llamada).Además, asegúrese de dar el contexto adecuado en la parte AJAX, de lo contrario 'esto' no funcionará en la devolución de llamada 'éxito':

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') 
10

Ha pasado un tiempo y puede que no haya sido posible en el momento, pero se puede llamar al método ajax de su adaptador directamente:

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

Por ejemplo:

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

Para su pregunta:

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

Edición - usando buildURL es útil, sobre todo si ha configurado un espacio de nombres en el adaptador:

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

Edición 2 - También puede obtener el adaptador con container.lookup('adapter:application'), que es útil si no tiene acceso global a la aplicación (por ejemplo, módulos ES6/ember-cli)

Editar 3 - Lo anterior se refiere a una versión obsoleta de Ember/Ember-CLI. Ahora defino esta función en un mixin -

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 

y lo llaman como tal -

@customAjax('PUT', 'modelClass', modelId, 'nonCRUDActionName', optionalHashOfAdditionalData).then (response) => 
    #do something with response 
Cuestiones relacionadas