Skip to content

Instantly share code, notes, and snippets.

@arcreative
Last active September 25, 2019 23:34
Show Gist options
  • Save arcreative/2f338dd8915c3a76f63f63d36830937c to your computer and use it in GitHub Desktop.
Save arcreative/2f338dd8915c3a76f63f63d36830937c to your computer and use it in GitHub Desktop.
JSONAPI::Resources failure when trying to include models on a polymorphic association
begin
require 'bundler/inline'
require 'bundler'
rescue LoadError => e
STDERR.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true, ui: ENV['SILENT'] ? Bundler::UI::Silent.new : Bundler::UI::Shell.new) do
source 'https://rubygems.org'
gem 'rails', '~> 5.2.3', require: false
gem 'sqlite3', platform: :mri
gem 'audited', '~> 4.9.0'
gem 'activerecord-jdbcsqlite3-adapter',
git: 'https://github.com/jruby/activerecord-jdbc-adapter',
# branch: 'rails-5',
platform: :jruby
if ENV['JSONAPI_RESOURCES_PATH']
gem 'jsonapi-resources', path: ENV['JSONAPI_RESOURCES_PATH'], require: false
else
gem 'jsonapi-resources', '~> 0.9.10', require: false
end
end
# prepare active_record database
require 'active_record'
class NullLogger < Logger
def initialize(*_args)
end
def add(*_args, &_block)
end
end
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = ENV['SILENT'] ? NullLogger.new : Logger.new(STDOUT)
ActiveRecord::Migration.verbose = !ENV['SILENT']
ActiveRecord::Schema.define do
create_table "users", force: :cascade do |t|
t.string "name", null: false
end
create_table "roles", force: :cascade do |t|
t.string "name", null: false
end
create_table "role_applications", force: :cascade do |t|
t.integer "role_id", null: false
t.integer "applicant_id", null: false
t.string "state", null: false, default: 'pending'
t.index ["applicant_id"], name: "index_role_applications_on_applicant_id"
t.index ["role_id", "applicant_id"], name: "index_role_applications_on_role_id_and_applicant_id", unique: true
t.index ["role_id"], name: "index_role_applications_on_role_id"
end
create_table "audits", force: :cascade do |t|
t.integer "auditable_id"
t.string "auditable_type"
t.integer "associated_id"
t.string "associated_type"
t.integer "user_id"
t.string "user_type"
t.string "username"
t.string "action"
t.text "audited_changes"
t.integer "version", default: 0
t.string "comment"
t.string "remote_address"
t.string "request_uuid"
t.datetime "created_at"
t.index ["associated_id", "associated_type"], name: "associated_index"
t.index ["auditable_id", "auditable_type"], name: "auditable_index"
t.index ["created_at"], name: "index_audits_on_created_at"
t.index ["request_uuid"], name: "index_audits_on_request_uuid"
t.index ["user_id", "user_type"], name: "user_index"
end
end
# create models
class ApplicationModel < ActiveRecord::Base
self.abstract_class = true
audited
end
class Role < ApplicationModel
has_many :applications, class_name: 'RoleApplication'
end
class RoleApplication < ApplicationModel
belongs_to :applicant, class_name: 'User'
belongs_to :role
enum state: { pending: 'pending', foo: 'foo', bar: 'bar', baz: 'baz' }
end
class User < ApplicationModel
has_many :applications, class_name: 'RoleApplication', foreign_key: :applicant_id
end
# prepare rails app
require 'action_controller/railtie'
# require 'action_view/railtie'
require 'jsonapi-resources'
class ApplicationController < ActionController::Base
end
# prepare jsonapi resources and controllers
class ApiController < ApplicationController
include JSONAPI::ActsAsResourceController
end
module Api
module V1
class AuditsController < ApiController; end
class RolesController < ApiController; end
class RoleApplicationsController < ApiController; end
class UsersController < ApiController; end
class AuditResource < JSONAPI::Resource
model_name 'Audited::Audit'
has_one :auditable, polymorphic: true
end
class RoleResource < JSONAPI::Resource
has_many :applications
end
class RoleApplicationResource < JSONAPI::Resource
has_one :role
has_one :applicant
end
class UserResource < JSONAPI::Resource
has_many :applications
end
end
end
class TestApp < Rails::Application
config.root = File.dirname(__FILE__)
config.logger = ENV['SILENT'] ? NullLogger.new : Logger.new(STDOUT)
Rails.logger = config.logger
secrets.secret_token = 'secret_token'
secrets.secret_key_base = 'secret_key_base'
config.eager_load = false
end
# initialize app
Rails.application.initialize!
JSONAPI.configure do |config|
config.json_key_format = :underscored_key
config.route_format = :underscored_key
end
# draw routes
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
jsonapi_resources :audits, only: [:index, :show]
jsonapi_resources :roles, only: [:index, :show]
jsonapi_resources :role_applications, only: [:index, :show]
jsonapi_resources :users, only: [:index, :show]
end
end
end
# prepare tests
require 'minitest/autorun'
require 'rack/test'
# Replace this with the code necessary to make your test fail.
class BugTest < Minitest::Test
include Rack::Test::Methods
def json_api_headers
{'Accept' => JSONAPI::MEDIA_TYPE, 'CONTENT_TYPE' => JSONAPI::MEDIA_TYPE}
end
def test_index_your_models
applicant = User.create! id: 1, name: 'Testy Testerson'
role = Role.create! id: 1, name: 'Some random role'
application = RoleApplication.create! id: 1, role: role, applicant: applicant
application.update(state: :foo)
application.update(state: :bar)
application.update(state: :baz)
assert application.reload.audits.count == 4
get '/api/v1/audits', nil, json_api_headers
assert last_response.ok?
json_response = JSON.parse(last_response.body)
refute_nil json_response['data']
refute_empty json_response['data']
refute_empty json_response['data'].first
# Should fail
get '/api/v1/audits?include=auditable', nil, json_api_headers
end
private
def app
Rails.application
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment