RAILS and STI: failure to detect table inheritance, crash

I’ve got code like this:

class ItineraryPricing
  # with a type column on the itinerary_pricings table
  belongs_to :itinerary, class_name: 'Roundtrip'
end

module Provider
   module Amadeus
      class ItineraryPricing < ::ItineraryPricing
     end
  end
end

class Roundtrip
  has_one :itinerary_pricing, foreign_key: :itinerary_id, dependent: :delete
end

Expected behavior

Forest should correctly detect STI tables.

Actual behavior

Forest is crashing while trying to view Roundtrips

Your server encountered an error

While everything goes fine in rails console or through Sidekiq and Puma.

Failure Logs

[2021-01-20 17:26:59] Forest :deciduous_tree::deciduous_tree::deciduous_tree: Records Index error: Invalid single-table inheritance type: Providers::Amadeus::Flights::ItineraryPricing is not a subclass of ItineraryPricing
/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/inheritance.rb:233:in `find_sti_class’

Context

RAILS 5.2.4.4

  • Package Version: 5.4.0 (Gem)
  • Database Dialect: Postgresql (standard SQL)
  • Database Version: 11
  • Project Name: Okarito / YVES DEVELOPMENT

Hi @yld, and welcome to our community :raised_hands:

From what I can see in the code, STI table should be supported.
I did a quick test on my end and I did not spot any issue around this, but I may have missed something.

A few question in order to debug this:

  • Is this this whole stack trace?
  • Could you share a more detailed insight of this part of your database structure/fields definition?
  • Do you have another environment I can compare YVES DEVELOPMENT where you do not have this issue ?

Thanks in advance

1 Like

No it wasn’t, here it is:

[2021-01-21 11:39:11] Forest 🌳🌳🌳  Records Index error: Invalid single-table inheritance type: Providers::Amadeus::Flights::ItineraryPricing is not a subclass of ItineraryPricing
/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/inheritance.rb:233:in `find_sti_class'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/inheritance.rb:207:in `discriminate_class_for_record'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/persistence.rb:69:in `instantiate'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency/join_part.rb:66:in `instantiate'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency.rb:248:in `construct_model'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency.rb:231:in `block in construct'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency.rb:208:in `each'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency.rb:208:in `construct'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency.rb:119:in `block (2 levels) in instantiate'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/result.rb:57:in `block in each'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/result.rb:57:in `each'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/result.rb:57:in `each'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency.rb:116:in `block in instantiate'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/associations/join_dependency.rb:115:in `instantiate'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation.rb:556:in `block (2 levels) in exec_queries'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation/finder_methods.rb:398:in `apply_join_dependency'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation.rb:550:in `block in exec_queries'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation.rb:584:in `skip_query_cache_if_necessary'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation.rb:547:in `exec_queries'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation.rb:422:in `load'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation.rb:200:in `records'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/relation.rb:195:in `to_ary'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/forest_liana-5.4.0/app/services/forest_liana/resources_getter.rb:82:in `records'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/forest_liana-5.4.0/app/controllers/forest_liana/resources_controller.rb:224:in `render_jsonapi'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/forest_liana-5.4.0/app/controllers/forest_liana/resources_controller.rb:36:in `block (2 levels) in index'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal/mime_responds.rb:203:in `respond_to'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/forest_liana-5.4.0/app/controllers/forest_liana/resources_controller.rb:35:in `index'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/abstract_controller/base.rb:194:in `process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal/rendering.rb:30:in `process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/abstract_controller/callbacks.rb:42:in `block in process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/callbacks.rb:132:in `run_callbacks'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/abstract_controller/callbacks.rb:41:in `process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal/rescue.rb:22:in `process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/notifications.rb:168:in `block in instrument'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/notifications.rb:168:in `instrument'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/abstract_controller/base.rb:134:in `process'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionview-5.2.4.4/lib/action_view/rendering.rb:32:in `process'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal.rb:191:in `dispatch'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_controller/metal.rb:236:in `block in action'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/forest_liana-5.4.0/app/controllers/forest_liana/router.rb:40:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/routing/mapper.rb:19:in `block in <class:Constraints>'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/routing/mapper.rb:48:in `serve'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/journey/router.rb:52:in `block in serve'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/journey/router.rb:35:in `each'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/journey/router.rb:35:in `serve'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/routing/route_set.rb:840:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-cors-1.1.1/lib/rack/cors.rb:100:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/railties-5.2.4.4/lib/rails/engine.rb:524:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/railties-5.2.4.4/lib/rails/railtie.rb:190:in `public_send'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/railties-5.2.4.4/lib/rails/railtie.rb:190:in `method_missing'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/routing/mapper.rb:19:in `block in <class:Constraints>'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/routing/mapper.rb:48:in `serve'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/journey/router.rb:52:in `block in serve'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/journey/router.rb:35:in `each'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/journey/router.rb:35:in `serve'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/routing/route_set.rb:840:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-attack-6.2.2/lib/rack/attack.rb:170:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/versionist-2.0.1/lib/versionist/middleware.rb:39:in `_call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/versionist-2.0.1/lib/versionist/middleware.rb:17:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/warden-1.2.9/lib/warden/manager.rb:36:in `block in call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/warden-1.2.9/lib/warden/manager.rb:34:in `catch'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/warden-1.2.9/lib/warden/manager.rb:34:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/etag.rb:27:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/conditional_get.rb:27:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.4/lib/active_record/migration.rb:559:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/callbacks.rb:98:in `run_callbacks'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/executor.rb:14:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/appsignal-2.10.2/lib/appsignal/rack/rails_instrumentation.rb:19:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/railties-5.2.4.4/lib/rails/rack/logger.rb:38:in `call_app'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/railties-5.2.4.4/lib/rails/rack/logger.rb:26:in `block in call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/tagged_logging.rb:71:in `block in tagged'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/tagged_logging.rb:28:in `tagged'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-5.2.4.4/lib/active_support/tagged_logging.rb:71:in `tagged'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/railties-5.2.4.4/lib/rails/rack/logger.rb:26:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/request_id.rb:27:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/runtime.rb:22:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/executor.rb:14:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-5.2.4.4/lib/action_dispatch/middleware/static.rb:127:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/sendfile.rb:110:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/rack-cors-1.1.1/lib/rack/cors.rb:100:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/railties-5.2.4.4/lib/rails/engine.rb:524:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/puma-4.3.6/lib/puma/configuration.rb:228:in `call'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/puma-4.3.6/lib/puma/server.rb:713:in `handle_request'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/puma-4.3.6/lib/puma/server.rb:472:in `process_client'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/puma-4.3.6/lib/puma/server.rb:328:in `block in run'
	/Users/yves/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/puma-4.3.6/lib/puma/thread_pool.rb:134:in `block in spawn_thread'

Here is the migration for the itinerary_pricings table

class CreateItineraryPricings < ActiveRecord::Migration[5.2]
  def change
    create_table :itinerary_pricings do |t|
      t.string :type, null: false
      t.references :itinerary, foreign_key: {to_table: :roundtrips}, null: false
      t.string :provider_id, null: true
      t.jsonb :provider_attributes, default: '{}', null: false

      t.timestamps
    end

    add_index :itinerary_pricings, %i[type itinerary_id]
    add_index :itinerary_pricings, :provider_id, where: "(provider_id IS NOT NULL)"
  end
end

A roundtrips table with a simple ID should do it.

The environment i’m using is a pure copy of Okarito PRODUCTION with an updated .forestadmin-schema.json.

Hi @yld,

Sadly, I’m still not able to reproduce on my end.

The errors mentions Providers::Amadeus::Flights::ItineraryPricing, but it seems that Flights is missing from your

module Provider
   module Amadeus
      class ItineraryPricing < ::ItineraryPricing
     end
  end
end

Also, I found some references to Providers::Amadeus::Flights::ItineraryPricing, and Providers::Amadeus::Flights::ItineraryPricings in the generated schema. Are these different classes ?

1 Like

Sorry, it tried to obfuscate several things without luck.

The model is written as follow (no more stripped code):

module Providers
  module Amadeus
    module Flights
      class ItineraryPricing < ::ItineraryPricing
        store_accessor :provider_attributes
        validates :provider_attributes, presence: true, allow_blank: false
      end
    end
  end
end

Apart from the Forest schema, the only ItineraryPricings occurence i found was in the migration name i posted earlier.

Please note:

  • i have 3 others STI models structured almost alike. They all fail with the same kind of error.
  • the modules definitions are provided in some other parts of the code (app/services)

Hi @yld,

I spent the previous hour trying, but I’m still not able to. On my end, everything works as expected. I added a similar structure as yours (app/services with a Provider::xxx:yyy < ::MyClass, …) and still no luck.

I even added a second Provider implementing MyClass, just for the test, but even with that, still no luck.

The only way I managed to get a similar error was to … remove the inheritance in the provider, which gives me

[2021-01-21 15:49:32] Forest 🌳🌳🌳  Records Index error: Invalid single-table inheritance type: Provider::Living::Animal is not a subclass of Animal

Did you test this with the Provider definition inside the models?

1 Like

Nope.

Maybe something went bad from the GUI call… in my logs i see this:

Started GET "/forest/Roundtrip?fields%5BRoundtrip%5D=status%2Ccreated_at%2Creturn_date%2Creturn_airport%2Cbooking_reference%2Cid%2Cprice_cents_with_options%2Cflexibility%2Cparent%2Cparent_segment_ids%2Citinerary_pricing&fields%5Bitinerary_pricing%5D=id&fields%5Bparent%5D=id&filters=%7B%22field%22%3A%22supplier%22%2C%22operator%22%3A%22not_equal%22%2C%22value%22%3A%22trainline%22%7D&page%5Bnumber%5D=1&page%5Bsize%5D=10&searchExtended=0&sort=-id&timezone=Africa%2FAbidjan" for ::1 at 2021-01-21 16:23:22 +0100
Processing by ForestLiana::UserSpace::RoundtripController#index as JSON
  Parameters: {"fields"=>{"Roundtrip"=>"status,created_at,return_date,return_airport,booking_reference,id,price_cents_with_options,flexibility,parent,parent_segment_ids,itinerary_pricing", "itinerary_pricing"=>"id", "parent"=>"id"}, "filters"=>"{\"field\":\"supplier\",\"operator\":\"not_equal\",\"value\":\"trainline\"}", "page"=>{"number"=>"1", "size"=>"10"}, "searchExtended"=>"0", "sort"=>"-id", "timezone"=>"Africa/Abidjan", "collection"=>"Roundtrip"}
(then the stack trace previously given)

Why is there itinerary_pricing", "itinerary_pricing"=>"id" in the parameters?

Hi @yld ,

Why is there itinerary_pricing", "itinerary_pricing"=>"id" in the parameters?

It’s because you certainly display the itinerary_pricing column in the UI, no ?

Hi guys, Remi here (Yves’ colleague) from Okarito.

We’ve moved about models definition to our models file but it doesn’t fix the bug.

Here are my models definitions

#okarito/okarito-api/app/models/providers/amadeus/flights/itinerary_pricing.rb

# frozen_string_literal: true

module Providers
  module Amadeus
    module Flights
      class ItineraryPricing < ::ItineraryPricing
      end
    end
  end
end
#okarito/okarito-api/app/models/itinerary_pricing.rb

class ItineraryPricing < ApplicationRecord
  belongs_to :itinerary, class_name: 'Roundtrip'
  validates :type, presence: true
end

In my Rails console,

 pry(main)> ItineraryPricing.first
  ItineraryPricing Load (13.4ms)  SELECT  "itinerary_pricings".* FROM "itinerary_pricings" ORDER BY "itinerary_pricings"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> #<Providers::Amadeus::Flights::ItineraryPricing:0x00007ffcc4fabf90
 id: 1,
 type: "Providers::Amadeus::Flights::ItineraryPricing",
 itinerary_id: 15848,
 provider_id: nil,
 provider_attributes: "true",
 created_at: Fri, 05 Feb 2021 15:07:31 UTC +00:00,
 updated_at: Fri, 05 Feb 2021 15:07:31 UTC +00:00>


[10] pry(main)> ItineraryPricing.descendants
=> [Providers::Amadeus::Flights::ItineraryPricing(id: integer, type: string, itinerary_id: integer, provider_id: string, provider_attributes: jsonb, created_at: datetime, updated_at: datetime)]

In my forestadmin.json file

...
{
    "name": "ItineraryPricing",
    "name_old": "__itinerary_pricings",
    "icon": null,
    "is_read_only": false,
    "is_searchable": true,
    "is_virtual": false,
    "only_for_relationships": false,
    "pagination_type": "page",
    "fields": [{
      "field": "id",
      "type": "Number",
      "default_value": null,
      "enums": null,
      "integration": null,
      "is_filterable": true,
      "is_read_only": false,
      "is_required": false,
      "is_sortable": true,
      "is_virtual": false,
      "reference": null,
      "inverse_of": null,
      "widget": null,
      "validations": []
    }, {
      "field": "type",
      "type": "Enum",
      "default_value": null,
      "enums": ["Providers::Amadeus::Flights::ItineraryPricing"],
      "integration": null,
      "is_filterable": true,
      "is_read_only": false,
      "is_required": true,
      "is_sortable": true,
      "is_virtual": false,
      "reference": null,
      "inverse_of": null,
      "widget": null,
      "validations": [{
        "message": null,
        "type": "is present"
      }]
...

I believe the setup of our tables is functional (it works fine in our app) but it still crashes when we try to display ou forestadmin views.

Is anyone on your team able to reproduce ?

Thanks,

Remi

Hi @remi_okarito !
I’m not sure if you already saw that or not, but type should not be used as a column name because it is a reserved word for ActiveRecord.
More about that here.
Let me know if it helps you !

I’m not sure if you already saw that or not, but type should not be used as a column name because it is a reserved word for ActiveRecord.
More about that here .

Thanks, type is required for STI models to work, which is precisely the case here.

Let me know if it helps you !

Not at all.

For the record, we are still investigating on this issue.
Unfortunately, the team does not (yet) manage to create a minimal, reproducible project example.

Hello Forest team,

after some debug a few months ago with @Steve_Bunlon we realized that the issue was about the caching of classes (that is disabled in development mode). STI classes are not cached and cannot be loaded by Forest which causes that crash.

@Steve_Bunlon found a workaround (caching classes in development mode) but it makes the development process a lot more frustrating - we need to restart our server on every class change.

Is there a plan for integrating a better solution in the gem ?

Let us know !

Remi

Hi @remi_okarito,

In the short term, we do not have planned a better solution, sorry for that.
I’ve just created a product ticket to ask for it.

ActiveRecord is aware of this problem, so they also may fix the problem’s root cause before we have a workaround.

Regards

Quick update here, upgrading our Rails app to Rails 6.x fixed the issue. Probably something related to Zeitwerk loading. Telling future Rails customers to upgrade to Rails 6 to be able to use complex STI setups sounds like a good idea :wink:

3 Likes

:tada: Glad to hear it solved your problem!