0

J'ai un problème avec les types de discordances dans mon API chaque fois que je veux créer un nouvel élément.Comment réparer une API en utilisant jsonapi-resources qui répond avec un type de discordance et ne me permet pas de créer des enregistrements?

Il arrive en 2 endroits:

  1. lorsque je tente de publier un nouvel élément

POST http://localhost:8060/datasets/

{ 
    "data": { 
      "type": "datasets", 
      "attributes": { 
       "doi": "10.5259/2008120816KAKA", 
       "version": 0, 
       "is-active": "1", 
       "datacentre": 201 
      } 
    } 

Réponse

"errors": [ 
    { 
     "title": "Internal Server Error", 
     "detail": "Internal Server Error", 
     "code": "500", 
     "status": "500", 
     "meta": { 
      "exception": "Datacentre(#23863440) expected, got 201 which is an instance of Fixnum(#4211740)", 
      "backtrace": [ 
       "/usr/local/rvm/gems/ruby-2.3.3/gems/activerecord-5.1.1/lib/active_record/associations/association.rb:239:in `raise_on_type_mismatch!'", 
       "/usr/local/rvm/gems/ruby-2.3.3/gems/activerecord-5.1.1/lib/active_record/associations/belongs_to_association.rb:11:in `replace'", 
       "/usr/local/rvm/gems/ruby-2.3.3/gems/activerecord-5.1.1/lib/active_record/associations/singular_association.rb:15:in `writer'", 
       "/usr/local/rvm/gems/ruby-2.3.3/gems/activerecord-5.1.1/lib/active_record/associations/builder/association.rb:119:in `datacentre='" 
  1. Je peux le voir se produire lors de l'accès aux relations d'un article. Par exemple, c'est une réponse GET:

GET http://localhost:8060/datasets/

{ 
    "data": [ 
     { 
      "id": "5", 
      "type": "datasets", 
      "links": { 
       "self": "http://localhost:8060/datasets/5" 
      }, 
      "attributes": { 
       "created": "2011-03-02T16:41:20.000Z", 
       "doi": "10.5259/20070410230000/HTTP://www.STAFFSPASTTRACK.ORG.UK/EXHIBIT/CRIMEANDPUNISHMENT/IMAGEPAGE/ZERO.HTM", 
       "version": 0, 
       "is-active": "", 
       "updated": "2011-03-02T16:41:20.000Z", 
       "datacentre": "#<Datacentre:0x000000033389b8>", 
       "deposited": "2012-07-31T09:12:37.000Z" 
      }, 
      "relationships": { 
       "datacentre": { 
        "links": { 
         "self": "http://localhost:8060/datasets/5/relationships/datacentre", 
         "related": "http://localhost:8060/datasets/5/datacentre" 
        } 
       } 
      } 
     } 

Vous pouvez voir comment l'attribut datacentre (FOREIGN_KEY) est présenté comme un type d'objet du Modèle Datacentre. Si je tente d'accéder à la relantship à ce modèle http://localhost:8060/datasets/5/datacentre j'obtiens ce qui suit:

{ 
* errors: [ 
* { 
* title: "Internal Server Error", 
* detail: "Internal Server Error", 
* code: "500", 
* status: "500", 
* meta: { 
* exception: "Unknown source type #<Datacentre id: 10015, comments: "", contact_email: "[email protected]", contact_name: "Andy Jackson", created: "2010-12-14 22:05:32", doi_quota_allowed: 50000, doi_quota_used: 17, domains: "webarchive.org.uk", is_active: "\x01", name: "Web Archive Programme at BL", password: "98583c1bf114bfe80105f906d800e05325307f06b93ccee6b6...", role_name: "ROLE_DATACENTRE", symbol: "BL.WAP", updated: "2012-02-17 11:49:01", version: 2, allocator: 106, experiments: nil>", 
* backtrace: [ 
* "/usr/local/rvm/gems/ruby-2.3.3/gems/jsonapi-resources-0.9.0/lib/jsonapi/resource_serializer.rb:267:in `top_level_source_key'", 
* "/usr/local/rvm/gems/ruby-2.3.3/gems/jsonapi-resources-0.9.0/lib/jsonapi/resource_serializer.rb:47:in `block in serialize_to_hash'", 
* "/usr/local/rvm/gems/ruby-2.3.3/gems/jsonapi-resources-0.9.0/lib/jsonapi/resource_serializer.rb:47:in `map'", 
* "/usr/local/rvm/gems/ruby-2.3.3/gems/jsonapi-resources-0.9.0/lib/jsonapi/resource_serializer.rb:47:in `serialize_to_hash'", 
* "/usr/local/rvm/gems/ruby-2.3.3/gems/jsonapi-resources-0.9.0/lib/jsonapi/response_document.rb:109:in `results_to_hash'", 
* "/usr/local/rvm/gems/ruby-2.3.3/gems/jsonapi-resources-0.9.0/lib/jsonapi/response_document.rb:12:in `contents’”, 

Je pense que le problème est que l'API attend le mauvais type d'objet. Il s'attend Datacentre quand il devrait attendre DatacentreResource.

Ma configuration est la suivante:

  • J'ai une base de données Legacy qui ne suit pas les conventions de nommage des tables ActiveRecord et FOREIGN_KEYS.
  • Les tables sont singulières et les clés étrangères n'ont pas le suffixe _id.
  • Les tables/modèles dans lesquels j'ai le problème ont une relation one_to_many. La relation étant un datacentre a beaucoup de datasets. J'utilise jsonapi-resources et rails 5 api-only.

Datacentre Modèle

class Datacentre < ApplicationRecord 
    self.table_name = "datacentre" 
    alias_attribute :allocator_id, :allocator 
    has_and_belongs_to_many :prefixes, class_name: 'Prefix', join_table: "datacentre_prefixes", foreign_key: :prefixes, association_foreign_key: :datacentre 
    belongs_to :allocator, class_name: 'Allocator', foreign_key: :allocator 
    has_many :datasets 
end 

Dataset Modèle

class Dataset < ApplicationRecord 
    self.table_name = "dataset" 
    alias_attribute :datacentre_id, :datacentre 
    belongs_to :datacentre, class_name: 'Datacentre', foreign_key: :datacentre 
end 

Datacentre ressources

class DatacentreResource < JSONAPI::Resource 
    model_name 'Datacentre' 
    model_hint model: Datacentre 
    attributes :comments, :contact_email, :contact_name, :created, :doi_quota_allowed, :doi_quota_used, :domains, :is_active, :name, :password, :role_name, :symbol, 
    :updated, :version, :experiments, :allocator 
    has_many :datasets 
    has_many :prefixes 
    has_one :allocator, class_name: 'Allocator', foreign_key: :allocator 
end 

Dataset ressources

class DatasetResource < JSONAPI::Resource 
    model_name 'Dataset' 
    model_hint model: Dataset 
    attributes :created, :doi, :version, :is_active, :updated, :datacentre 
    attribute :deposited 
    has_one :datacentre, class_name: "Datacentre", foreign_key: :datacentre 
end 

Jusqu'ici j'ai contourné le premier problème (c.-à-d.l'accès à la relation) en modifiant les méthodes pour datacentre et son alias datacentre_id dans la ressource Dataset

def datacentre(context=nil) 
    DatacentreResource.find_by_key(@model.datacentre.id) 
end 

    def datacentre_id() 
    @model.datacentre.id 
end 

Mais cela ne résout pas le problème POST.

Répondre

0

Je pense que c'est la chose qui provoque l'erreur

dans

class Dataset < ApplicationRecord 
    self.table_name = "dataset" 
    alias_attribute :datacentre_id, :datacentre 
    belongs_to :datacentre, class_name: 'Datacentre', foreign_key: :datacentre 
end 

datacentre_id et datacentre sont aliasées il rend et objet datacentre retour en réponse au lieu de datacentre_id

probablement wokr si vous supprimez cette ligne