0

每次我想创建一个新项目时,我的 API 中的不匹配类型都会出现问题。

它发生在两个地方:

  1. 当我尝试发布新项目时

POST http://localhost:8060/datasets/

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

回复

    "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. 我可以在访问项目的关系时看到它发生。例如,这是一个 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"
                    }
                }
            }
        }

您可以看到datacentre(foreign_key) 属性如何呈现为Model Datacenter的对象类型。如果我尝试访问与该模型的关系,http://localhost:8060/datasets/5/datacentre我会得到以下信息:

{
* errors: [
* {
* title: "Internal Server Error",
* detail: "Internal Server Error",
* code: "500",
* status: "500",
* meta: {
* exception: "Unknown source type #<Datacentre id: 10015, comments: "", contact_email: "andrew.jackson@bl.uk", 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’”,

我认为问题在于 API 期望的对象类型错误。当它应该期待DatacentreResource时,它​​期待Datacentre

我的设置如下:

  • 我有一个旧版数据库,它不遵循 ActiveRecord 命名表和外键的约定。
  • 表是单数的,foreign_keys 没有 _id 后缀。
  • 我遇到问题的表/模型具有 one_to_many 关系。
  • 关系是datacentrehas_many datasets
  • 我正在使用jsonapi-resources和 rails 5 api-only

数据中心模型

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

数据集模型

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

数据中心资源

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

数据集资源

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

到目前为止,我通过修改数据集资源中的方法datacentre及其别名解决了第一个问题(即访问关系)datacentre_id

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

  def datacentre_id()
    @model.datacentre.id
 end

但这并不能解决 POST 问题。

4

1 回答 1

0

我认为这是导致错误的原因

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

datacentre_id并且datacentre是别名,因此它会返回并返回对象datacentre作为响应,而不是datacentre_id

如果您删除此行,它可能会起作用

于 2017-08-25T14:24:39.693 回答