#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
inUserResource
. Я предполагаю, чтоrelationship
это соответствуетbelongs_to
. jsonapi-resources.com/v0.10/guide/resources.html#Relationships5. Не повезло с этим: (Это оскорбительный код в библиотеке: github.com/cerebris/jsonapi-resources/blob/v0.10.2/lib/jsonapi /. … Заметил, что он только смотрел
has_many
, поэтому не уверен, имеет ли это какое-то отношение к этому