2013-02-12 14 views
11

Cheers! Ho negozio brace-dati:Ember.js ember-data restadapter non riesce a caricare json

TravelClient.Store = DS.Store.extend({ 
    revision: 11, 
    adapter: DS.RESTAdapter.create({ bulkCommit: false, url: "http://someIP:somePORT"}) 
}); 

E router:

TravelClient.ToursRoute = Ember.Route.extend({ 
    model: function() { 
    return TravelClient.Tour.find(); 
    } 
}); 

ricevo questo JSON dal server remoto:

{ 
    "tours": [ 
    { 
     "id": "5110e8b5a8fefe71e0000197", 
     "title": "qui deserunt dolores", 
     "description": "Id velit nihil.", 
     "seats": 12, 
     "options": [ 

     ], 
     "images": [ 
     { 
      "id": "5110e8b5a8fefe71e0000196", 
      "url": "url" 
     } 
} 

Ma quando provo a return TravelClient.Tour.find() non riesce con:

http://someIP:somePORT/tours 404 (Not Found) 

XMLHttpRequest cannot load http://someIP:somePORT/tours. Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin. 

Sembra che RESTAdapter non sappia, che debba ricevere JSON o cosa?

UPDATE:

Nel controllore dell'applicazione sulle rotaie sul lato server:

def set_access_control_headers 
    headers['Access-Control-Allow-Origin'] = '*' 
    headers['Access-Control-Request-Method'] = '*' 
end 

Ma è ancora:

OPTIONS http://someIP:somePORT/tours 404 (Not Found) 

E sembra RESTAdapter tenta di caricare tour risorsa, non tours.json:

Request URL:http://someIP:somePORT/tours 

LAVORO SOLUZIONE

Estendere RESTAdapter:

TravelClient.CUSTOMAdapter = DS.RESTAdapter.extend({ 
    bulkCommit: false, 
    url: "http://remote_server_address",  
    buildURL: function(record, suffix) { 
    var s = this._super(record, suffix); 
    return s + ".json"; 
    } 
}) 

e rispondere a una richiesta OPTIONS con le intestazioni di destra

+0

le intestazioni impostate vengono restituiti con il 'GET' richiesta è necessario restituirli con una richiesta OPTIONS' – albertjan

+0

CORS Rack gemma' ha fatto il trucco, grazie. Penso che stia facendo tutte queste cose con le richieste di OPTIONS solo "out of the box". – xamenrax

+0

Ecco il link per il prossimo visitatore https://github.com/cyu/rack-cors ftw – genkilabs

risposta

10

Il RESTAdapter aspetta JSON che non è il problema, ma la pagina e il JSON non sono sullo stesso dominio, questo è un problema di sicurezza. È possibile risolvere questo problema utilizzando una delle due soluzioni indicate di seguito.

Si sta eseguendo nel same origin policy si dovrebbe utilizzare JSONP o CORS. La soluzione più rapida sarebbe probabilmente quella di dire a dati di terra che vuoi usare JSONP.

Per CORS il server ha bisogno di rispondere ad una richiesta di OPTIONS con le intestazioni:

  • Access-Control-Allow-Origin
  • Access-Control-Request-Method

Non sono un esperto rotaie, ma si avrà probabilmente bisogno di fare qualcosa con la gemma rack-cors vedi here o here.

Si potrebbe fare che sovrascrivendo il gancio ajax nel RESTAdapter in questo modo:

App.store = DS.Store.create({ 
    revision: 11, 
    adapter: DS.RESTAdapter.create({ 
     namespace: "data", 
     url: "", 
     ajax: function (url, type, hash) { 
      hash.url = url; 
      hash.type = type; 
      hash.dataType = 'jsonp'; 
      hash.contentType = 'application/json; charset=utf-8'; 
      hash.context = this; 

      if (hash.data && type !== 'GET') { 
       hash.data = JSON.stringify(hash.data); 
      } 

      jQuery.ajax(hash); 
     }, 
    }) 
}); 
+0

Per utilizzare CORS ho solo bisogno di aggiungere smth come 'Access-Control-Allow-Origin: *' all'intestazione della risposta del server? – xamenrax

+0

si veda qui: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing e qui: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS Ci sono altre intestazioni che puoi controllare più specificamente ciò che è permesso. – albertjan

+0

Controllare l'aggiornamento, per favore. – xamenrax

1

Ho un semplice lavoro in giro in Rails (che sta lavorando per me finora.) E 'disordinato come è, ma può essere facilmente rafforzato con la logica nei controller.

In routes.rb:

match ':path' => 'authentications#allow', constraints: {method: 'OPTIONS'} 

che restituisce semplicemente stato OK a qualsiasi richiesta OPTIONS.

def allow 
    head :ok 
end 

E poi nel application_controller.rb impostare la condivisione delle risorse Cross-origine (CORS) intestazioni per ogni richiesta:

before_filter :cors 
def cors 
    response.headers.merge! 'Access-Control-Allow-Origin' => '*', 'Access-Control-Allow-Methods' => 'POST, PUT, GET, DELETE', 'Access-Control-Allow-Headers' => 'Origin, Accept, Content-Type' 
end 
+0

Ma non c'era niente di sbagliato nelle mie intestazioni, solo Rails mi stava restituendo in html, mentre io avevo bisogno di JSON. Quindi, la soluzione è semplicemente dire direttamente a Rails che si desidera che json - estenda il metodo buildURL dell'adattatore. Mi scusi per il mio inglese. – xamenrax

1

Se stai cercando di utilizzare JSONP è molto più facile per ignorare la funzione privata ajaxOptions invece di utilizzare jQuery e ignorare il metodo ajax. La pipeline di Ember include la rimozione della dipendenza jQuery. Quindi, fare questo, invece:

adapters/application.js:

import DS from 'ember-data'; 

export default DS.RESTAdapter.extend({ 
    ajaxOptions: function(url, type, options) { 
     var hash = this._super(url, type, options); 
     hash.dataType = "jsonp"; 
     return hash; 
    } 
}); 

Sarebbe creare se il core team Ember potrebbe esporre un metodo pubblico per supportare ufficialmente questo (invece che l'hacking un privato API).

https://github.com/emberjs/data/blob/1.0.0-beta.15/packages/ember-data/lib/adapters/rest_adapter.js#L915

Problemi correlati