ошибка с полиморфизмом и jsonapi-ресурсами

#ruby-on-rails #json-api #jsonapi-resources

#ruby-on-rails #json-api #jsonapi-ресурсы

Вопрос:

Я пытаюсь настроить полиморфную ассоциацию, используя jsonapi-resources gem в Rails 5.

У меня есть User модель, которая имеет вызываемую полиморфную ассоциацию profile , которая может иметь тип Inspector или Buyer . Вот усеченные модели:

 class User < ApplicationRecord
  belongs_to :profile, polymorphic: true
end

class Inspector < ApplicationRecord
  belongs_to :user
end

class Buyer < ApplicationRecord
  belongs_to :user
end
  

В users таблице есть соответствующие profile_id profile_type поля и для представления полиморфной ассоциации с inspectors и buyers . Все это работает, как и ожидалось, в нашей текущей настройке Rails, но я сталкиваюсь с ошибками при попытке настроить это для использования JSON: API jsonapi-resources .

А теперь соответствующие jsonapi-resources ресурсы и контроллеры (в соответствии с указаниями):

 class Api::V1::Mobile::UserResource < JSONAPI::Resource
  immutable
  attributes :name, :email
  has_one :profile, polymorphic: true
end

class Api::V1::Mobile::ProfileResource < JSONAPI::Resource
end

class Api::V1::Mobile::ProfilesController < Api::V1::Mobile::BaseController
end
  

Насколько я могу судить, теперь все должно быть настроено правильно, но при попадании в конечную точку я получаю следующую ошибку:

 "exception": "undefined method `collect' for nil:NilClass",
        "backtrace": [
          ".rvm/gems/ruby-2.6.5/gems/jsonapi-resources-0.10.2/lib/jsonapi/relationship.rb:77:in `resource_types'",
  

При изучении relationship.rb упомянутого в трассировке стека похоже, что он не может разрешить полиморфные типы, поэтому я попробовал следующее:

 class Api::V1::Mobile::UserResource < JSONAPI::Resource
  immutable
  attributes :name, :email
  has_one :profile, polymorphic: true, polymorphic_types: ['inspector', 'buyer']
end
  

Но, увы, еще одна ошибка: Can't join 'User' to association named 'inspector'; perhaps you misspelled it?

Заранее спасибо за любую помощь в настройке!

Ответ №1:

Основная проблема на самом деле не имеет ничего общего с jsonapi-ресурсами и заключается в ассоциациях. Обратной стороной belongs_to ресурса всегда является has_one или has_many , который указывает на внешний ключ в другой таблице (и наоборот).

 class User < ApplicationRecord
  belongs_to :profile, polymorphic: true
end

class Inspector < ApplicationRecord
  has_one :user, as: :profile
end

class Buyer < ApplicationRecord
  has_one :user, as: :profile
end
  

Наличие двух belongs_to ассоциаций, которые указывают друг на друга, означало бы, что у вас будут внешние ключи с обеих сторон, что является плохим дизайном БД из-за дублирования (должен быть только один источник истины) и на самом деле не будет работать в ActiveRecord, поскольку он будет записывать внешний ключ только с одной стороны, когда высвяжите две модели.

Комментарии:

1. Спасибо, @max! Я попробую внести это изменение. Тем не менее, Rails просто позволяет нам избежать двух belongs_to ассоциаций, даже если это технически неверно?

2. Rails фактически не рассматривает модель с обратной стороны, пока вы на самом деле не используете ассоциацию и не извлекаете записи. Это действительно то, что вы ожидаете от динамического языка, такого как Ruby, где большинство вещей решается во время выполнения.

3. Просто внес предложенные изменения, но я все еще получаю те же ошибки

4. Документы довольно нечеткие, но я думаю, что вам может понадобиться relationship :profile, polymorphic: true вместо has_one :profile in UserResource . Я предполагаю, что relationship это соответствует belongs_to . jsonapi-resources.com/v0.10/guide/resources.html#Relationships

5. Не повезло с этим: (Это оскорбительный код в библиотеке: github.com/cerebris/jsonapi-resources/blob/v0.10.2/lib/jsonapi /. … Заметил, что он только смотрел has_many , поэтому не уверен, имеет ли это какое-то отношение к этому