2013-02-12 3 views
11

À votre santé! Je magasin Ember-data:Ember.js ember-data restadapter ne parvient pas à charger json

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

Et routeur:

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

Je reçois ce JSON de serveur distant:

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

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

Mais lorsque je tente de return TravelClient.Tour.find() il échoue avec:

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. 

Il semble que RESTAdapter ne sait pas, qu'il doit recevoir JSON ou quoi?

MISE À JOUR:

Dans le contrôleur d'application sur le côté serveur rails:

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

Mais il est encore:

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

Et il semble que RESTAdapter tente de charger des visites ressource, pas tours.json:

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

TRAVAIL SOLUTION

Étendre 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"; 
    } 
}) 

et répondre à une requête OPTIONS avec les en-têtes droite

+0

les en-têtes que vous définissez sont retournés avec le 'GET' vous devez les retourner sur demande avec une demande' OPTIONS' – albertjan

+0

rack gem CORS a fait l'affaire, merci. Je pense qu'il fait tout ça avec des requêtes OPTIONS juste "out of the box". – xamenrax

+0

Heres le lien pour le visiteur suivant https://github.com/cyu/rack-cors ftw – genkilabs

Répondre

10

Le RESTAdapter attend JSON qui est pas le problème, mais la page et JSON ne sont pas sur le même domaine, c'est un problème de sécurité. Vous pouvez résoudre ce problème en utilisant l'une des deux solutions nommées ci-dessous. Vous devez utiliser JSONP ou CORS. La solution la plus rapide serait probablement de dire aux données d'ember que vous voulez utiliser JSONP.

Pour CORS votre serveur doit répondre à une OPTIONS demande avec les en-têtes:

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

Je ne suis pas expert en rails, mais vous aurez probablement besoin de faire quelque chose avec la gemme rack-cors voir here ou here.

Vous pouvez le faire en remplaçant le crochet ajax dans le RESTAdapter comme ceci:

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

Pour utiliser CORS, il suffit d'ajouter smth comme 'Access-Control-Allow-Origin: *' à l'en-tête de réponse du serveur? – xamenrax

+0

oui voir ici: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing et ici: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS Il y a d'autres en-têtes que vous pouvez contrôler plus précisément ce qui est autorisé. – albertjan

+0

Vérifiez la mise à jour, s'il vous plaît. – xamenrax

1

J'ai un travail simple autour de Rails (qui travaille pour moi jusqu'à présent.) Il est désordonné comme il est, mais peut facilement être resserré avec la logique dans les contrôleurs.

En routes.rb:

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

qui retourne simplement l'état OK à toute demande OPTIONS.

def allow 
    head :ok 
end 

Et puis dans application_controller.rb mis les en-têtes de partage des ressources croisées d'origine (CORS) pour chaque demande:

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

Mais il n'y avait rien de mal avec mes en-têtes, juste Rails me rendait html, alors que j'avais besoin de json. Donc, contournement dit directement à Rails que vous voulez json - étendre la méthode buildURL de l'adaptateur. Désolé pour mon anglais. – xamenrax

1

Si vous cherchez à utiliser JSONP il est beaucoup plus facile de remplacer la fonction ajaxOptions privée à la place d'utiliser jQuery et en remplaçant la méthode ajax. Le pipeline d'Ember inclut la suppression de la dépendance jQuery. Donc, faire à la place:

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; 
    } 
}); 

Ce serait créer si l'équipe de base Ember pourrait exposer une méthode publique pour soutenir officiellement cette (au lieu de piratage d'un api privé).

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

Questions connexes