JSONAPI-Resources / JSONAPI-Resources/jsonapi-resources
STI with non-default inheritance_column set on the class breaks has_many assoc
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Ruby
- Estrellas
- 2.3k
- Forks
- 546
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Descripción
Looks like the issue is here:
https://github.com/cerebris/jsonapi-resources/blob/v0.7.0/lib/jsonapi/resource_serializer.rb#L307
With a cursory glance, it looks like the STI attribute is hard-coded to 'type', though the with the problem I am seeing personally, it could be that or a polymorphic association (unlikely, but maybe both). Either way, the issue can be reproduced with the setup below.
Also, may not be the best idea to assume the model has an :id field, instead you should be reading type from the parent's inheritance_column attribute and its primary_key from it's primary_key attribute.
If I get a chance today, I will look into fixing this, but thought I would report it in case I am unable to get to it before I forget about it lol
Create a new rails app:
$ rvm use 2.1.2
$ rails --version
=> Rails 4.1.14
$ rails new testtest
$ cd testtest/
$ rails g model ParentModel i_got_an_sti_once:string poly_rel_uid:string poly_rel_type:string
$ rails g model HasManyChildModel uid:string
$ rake db:migrate
Add jsonapi-resources
# Gemfile
...
gem 'jsonapi-resources'
...
Add your routes
#./config/routes.rb
Rails.application.routes.draw do
jsonapi_resources :has_many_child_models, param: :uid
end
Add your controller
# ./app/controllers/has_many_child_controller.rb
class HasManyChildModelsController < ApplicationController
include JSONAPI::ActsAsResourceController
end
Add your parent model
# ./app/models/parent_model.rb
class ParentModel < ActiveRecord::Base
self.inheritance_column = 'i_got_an_sti_once' # That's not true :'(
end
Add your child model
# ./app/models/child_model.rb
class ChildModel < ParentModel
belongs_to :poly_rel, polymorphic: true
end
Add your model that has_many child models
# ./app/models/has_many_child_model.rb
class HasManyChildModel < ActiveRecord::Base
# attributes: :uid
has_many :child_models, as: :poly_rel, primary_key: :uid, foreign_key: :poly_rel_uid
end
Add your has_many_child_models resource
# ./app/resources/has_many_child_model_resource.rb
class HasManyChildModelResource < JSONAPI::Resource
has_many :child_models, polymorphic: true, foreign_key_on: :related
end
Add your child_model resource
# ./app/resources/child_model_resource.rb
class ChildModelResource < JSONAPI::Resource
end
Now, start you server:
$ rails s -p 3001
And navigate to:
http://localhost:3001/has_many_child_models?include=child_models
To see the error:
{
"errors":[
{
"title":"Internal Server Error",
"detail":"Internal Server Error",
"id":null,
"href":null,
"code":500,
"source":null,
"links":null,
"status":"500",
"meta":{
"exception":"SQLite3::SQLException: no such column: type: SELECT type, \"parent_models\".\"id\" FROM \"parent_models\" WHERE \"parent_models\".\"i_got_an_sti_once\" IN ('ChildModel') AND \"parent_models\".\"poly_rel_uid\" = ? AND \"parent_models\".\"poly_rel_type\" = ?",
"backtrace":[
"/Users/***/.rvm/gems/ruby-2.1.2/gems/sqlite3-1.3.11/lib/sqlite3/database.rb:91:in `initialize'",
"/Users/***/.rvm/gems/ruby-2.1.2/gems/sqlite3-1.3.11/lib/sqlite3/database.rb:91:in `new'",
"/Users/***/.rvm/gems/ruby-2.1.2/gems/sqlite3-1.3.11/lib/sqlite3/database.rb:91:in `prepare'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/sqlite3_adapter.rb:311:in `block in exec_query'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/abstract_adapter.rb:378:in `block in log'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/notifications/instrumenter.rb:20:in `instrument'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/abstract_adapter.rb:372:in `log'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/sqlite3_adapter.rb:298:in `exec_query'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/sqlite3_adapter.rb:510:in `select'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/abstract/database_statements.rb:24:in `select_all'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/abstract/query_cache.rb:68:in `block in select_all'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/abstract/query_cache.rb:83:in `cache_sql'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/abstract/query_cache.rb:68:in `select_all'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/relation/calculations.rb:172:in `pluck'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/associations/collection_proxy.rb:31:in `pluck'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:307:in `foreign_key_types_and_values'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:262:in `to_many_linkage'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:285:in `link_object_to_many'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:293:in `link_object'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:189:in `block in relationship_data'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:181:in `each'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:181:in `each_with_object'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:181:in `relationship_data'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:130:in `object_hash'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:102:in `block in process_primary'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:96:in `each'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:96:in `process_primary'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/resource_serializer.rb:39:in `serialize_to_hash'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/response_document.rb:111:in `results_to_hash'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/response_document.rb:11:in `contents'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/acts_as_resource_controller.rb:155:in `render_results'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/acts_as_resource_controller.rb:64:in `process_request'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/jsonapi-resources-0.7.0/lib/jsonapi/acts_as_resource_controller.rb:13:in `index'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal/implicit_render.rb:4:in `send_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/abstract_controller/base.rb:189:in `process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal/rendering.rb:10:in `process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/abstract_controller/callbacks.rb:20:in `block in process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:113:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:113:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:552:in `block (2 levels) in compile'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:502:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:502:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:86:in `run_callbacks'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/abstract_controller/callbacks.rb:19:in `process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal/rescue.rb:29:in `process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `block in instrument'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/notifications/instrumenter.rb:20:in `instrument'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `instrument'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal/instrumentation.rb:30:in `process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal/params_wrapper.rb:250:in `process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/railties/controller_runtime.rb:18:in `process_action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/abstract_controller/base.rb:136:in `process'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionview-4.1.14/lib/action_view/rendering.rb:30:in `process'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal.rb:196:in `dispatch'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_controller/metal.rb:232:in `block in action'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/routing/route_set.rb:82:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/routing/route_set.rb:82:in `dispatch'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/routing/route_set.rb:50:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/journey/router.rb:73:in `block in call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/journey/router.rb:59:in `each'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/journey/router.rb:59:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/routing/route_set.rb:692:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/etag.rb:23:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/conditionalget.rb:25:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/head.rb:11:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/params_parser.rb:27:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/flash.rb:254:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/session/abstract/id.rb:225:in `context'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/session/abstract/id.rb:220:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/cookies.rb:562:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/query_cache.rb:36:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.14/lib/active_record/migration.rb:380:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:82:in `run_callbacks'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/callbacks.rb:27:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/reloader.rb:73:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/remote_ip.rb:76:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/railties-4.1.14/lib/rails/rack/logger.rb:38:in `call_app'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/railties-4.1.14/lib/rails/rack/logger.rb:20:in `block in call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/tagged_logging.rb:68:in `block in tagged'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/tagged_logging.rb:26:in `tagged'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/tagged_logging.rb:68:in `tagged'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/railties-4.1.14/lib/rails/rack/logger.rb:20:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/request_id.rb:21:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/methodoverride.rb:21:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/runtime.rb:17:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/activesupport-4.1.14/lib/active_support/cache/strategy/local_cache_middleware.rb:26:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/lock.rb:17:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.14/lib/action_dispatch/middleware/static.rb:84:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/sendfile.rb:112:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/railties-4.1.14/lib/rails/engine.rb:514:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/railties-4.1.14/lib/rails/application.rb:144:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/lock.rb:17:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/content_length.rb:14:in `call'",
"/Users/******/.rvm/gems/ruby-2.1.2/gems/rack-1.5.5/lib/rack/handler/webrick.rb:60:in `service'",
"/Users/******/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/webrick/httpserver.rb:138:in `service'",
"/Users/******/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/webrick/httpserver.rb:94:in `run'",
"/Users/******/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/webrick/server.rb:295:in `block in start_thread'"
]
}
}
]
}
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comience en lib/jsonapi/resource_serializer.rb en la línea 307 y reproduzca el fallo con el endpoint has_many_child_models y la configuración include=child_models descrita en el issue. Compruebe cómo el serializer obtiene los valores de STI y primary key para la asociación y, a continuación, verifique que la solicitud se completa sin consultar la columna type inexistente y respeta los inheritance_column y primary_key configurados.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- rails, ruby
- Área
- api, backend
- Tipo de issue
- Error
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Estado de actividad
- Estancado
- Claridad
- Bastante claro
- Aptitud para principiantes
- 35/100