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:
- 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='"
- 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 dedatasets
. J'utilisejsonapi-resources
et rails 5api-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.