rubyruby-grapegrape-entity

Two files requiring each other in ruby


I'm building a web API with Ruby and Grape. I have two classes that requires each other which leads to a situation where I get uninitialized constant class errors. The place where I get the error is in the Entity class for Connector, see the example code below, which requires Card::Entity before it has been inintialized. Is there any way to solve this probelm without moving the Entity definitions to another file?

#card.rb
require_relative 'connector'
require_relative 'caption'

class Card < ActiveRecord::Base

  belongs_to  :medium
  belongs_to  :storyline

  has_many    :connectors, autosave: true
  has_many    :connected_cards, class_name: "Connector", foreign_key: "connected_card_id"
  has_many    :captions

  accepts_nested_attributes_for :connectors, :captions

  class Entity < Grape::Entity
    expose :id, documentation: { readonly: true }
    expose :cardtype
    expose :connectors, using: Connector::Entity
    expose :captions, using: Caption::Entity
  end
end

#connector.rb
require_relative 'card'

class Connector < ActiveRecord::Base
  has_one  :card
  has_one  :connected_card, :class_name => "Card", :foreign_key => "connected_card_id"

  class Entity < Grape::Entity
    expose :id, documentation: { readonly: true }
    expose :title
    expose :card, using: Card::Entity
    expose :connected_card, using: Card::Entity
  end
end

Solution

  • I don't know a lot about grape, but this could be solved by "pre declaring" the class:

    #card.rb
    require_relative 'caption'
    
    class Connector < ActiveRecord::Base
      # empty declaration just to make the import works
    end
    
    class Card < ActiveRecord::Base
      belongs_to  :medium
      belongs_to  :storyline
    
      has_many    :connectors, autosave: true
      has_many    :connected_cards, class_name: "Connector", foreign_key: "connected_card_id"
      has_many    :captions
    
      accepts_nested_attributes_for :connectors, :captions
      ...
    end
    

    Still, I think that QPaysTaxes may have a valid point about design here.