2012-03-14 14 views
12

Dire che ho il seguente modello brace-dati:azioni non CRUD con brace-dati

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

Questo comunica con un'applicazione Rails con il seguente API CRUD abbastanza standard:

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 

Tutto questo esegue il mapping a Ember-Data con lo Store/Adapter standard.

Tuttavia, diciamo che per "star" o "unstar" una persona, l'API non ci permette di farlo con l'azione di aggiornamento standard. Esiste un endpoint API specifico per questa azione:

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

Come si inserisce questa API con Ember Data?

Sembra che avrei bisogno di estendere DS.Store e DS.RESTAdapter in qualche modo, ma non sono sicuro dell'approccio migliore per renderli consapevoli di queste diverse azioni. È anche un po 'sbagliato che un adattatore generico per l'app debba essere a conoscenza delle persone protagoniste.

Nota che non ho alcun controllo sull'API, quindi non posso rendere POST /people/id consapevole di "starring" in modo che si adatti a un aggiornamento standard.

+0

Potrebbe accettare la mia risposta? La versione attualmente accettata non è più precisa – andorov

risposta

-1

Nel gruppo di discussione, Yehuda menzionato questo non è ancora possibile.

+0

Cheers, ho pensato che potrebbe essere il caso in cui nulla è saltato fuori nella fonte/test. – rlivsey

+0

Questo è ora possibile - vedi la mia risposta qui sotto – andorov

0

Forse un buon punto di partenza: https://github.com/beautifulnode/ember.request

non aveva ancora provato, ma sembra promettente nel tuo caso ...

+0

Grazie, ci sono alcune opzioni per la persistenza, ma al momento sto dando a ember-data un'inquadratura poiché prevedo che sarà l'impostazione predefinita in futuro. – rlivsey

+0

@rlivsey alla fine hai trovato un modo per aggirare le azioni non crude con i dati di ember e fare in modo che la tua soluzione venga postata qui. Grazie – brg

+0

@mike Ho guardato il codice sorgente di minutefavors che ha un'azione non crudele e il tag preferito # e nel tuo ** [Apps.TagView] (https://github.com/mikecrittenden/minutefavors/blob/master /app/assets/javascripts/app/views/favors/tag.js)** hai definito una funzione url che restituisce '/ favor/tags'. So che hai usato la risorsa ember per quell'app, come possiamo fare qualcosa di simile con restAdapter di ember-data. Grazie, – brg

0

Penso che in CQRS therms star e unstar siano comandi. Quindi dovresti dichiarare il modello PersonStar e lavorarci.

2

Sono andato con lo stesso problema, e risolto utilizzando una versione modificata di quello che è spiegato qui: Non-crud rails actions in Ember.js

In sostanza, è necessario utilizzare una chiamata Jquery AJAX, la parte importante per me è stato quello di cambiare il contentType per ottenere i dati di autenticazione da inviare nelle intestazioni delle richieste, piuttosto che nei dati di modulo (l'impostazione predefinita, se si includono i dati nella chiamata).Inoltre, assicurarsi di dare il giusto contesto nella parte AJAX, altrimenti 'questo' non funziona nella richiamata 'successo':

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

Stato un po 'e non può essere stato possibile, al momento, ma è possibile chiamare il metodo ajax della scheda direttamente:

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

Ad esempio:

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

Per la vostra domanda:

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

Modifica - utilizzando buildURL è utile, soprattutto se hai impostato uno spazio dei nomi sulla scheda:

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

Edit 2 - È anche possibile ottenere l'adattatore con container.lookup('adapter:application'), che è utile se non si dispone di accesso globale all'app (ex moduli ES6/ember-cli)

Modifica 3 - Quanto sopra si riferisce a una versione obsoleta di Ember/Ember-CLI. Ora io definisco questa funzione in 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 

e chiamarlo in questo modo -

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