grape each entity in a single file
Asked Answered
L

1

8

I want to have multiple classes inside grape entity file, this is the folder structure app/api/proj/api/v2/entities/committees.rb

module PROJ::API::V2::Entities
class Committee < Grape::Entity
expose :id

expose :name, :full_name, :email, :tag, :parent_id

expose :country do |entity, option|
  entity.parent.name if entity.parent.present?
end

# include Urls

private
  def self.namespace_path
    "committees"
  end
end

  class CommitteeWithSubcommittees < CommitteeBase
        # include ProfilePhoto 
        expose :suboffices, with: 'PROJ::API::V2::Entities::CommitteeBase'
      end

and inside the Grape API

present @committees, with: PROJ::API::V2::Entities::Committee

is working. but if I present with

present @committees, with: PROJ::API::V2::Entities::CommitteeList

It is not working. But it works when I move it to a new file named committee_list.rb inside entities.

Laryssa answered 15/4, 2017 at 13:9 Comment(0)
F
6

You seem to be missing some key information from your post because you have not defined a class named CommitteeList or CommitteeBase anywhere. I assume that you have defined them and that you did not supply that code.

The problem that you're running into has to do with how Rails autoloads classes. There is more information available elsewhere on this, but essentially you should ensure that your class names, modules names, directory names, and file names all match up. The reason that it works when you move your CommitteeList class to its own file is because Rails is able to find the class dynamically.

I've had to do some guess-work based on what you provided, but you want something that looks like this:

# app/api/proj/api/v2/entities/committee.rb
module PROJ::API::V2::Entities
  class Committee < Grape::Entity; end
end

# app/api/proj/api/v2/entities/committee_base.rb
module PROJ::API::V2::Entities
  class CommitteeBase; end
end

# app/api/proj/api/v2/entities/committee_with_subcommittee.rb
module PROJ::API::V2::Entities
  class CommitteeWithSubcommittee < CommitteeBase; end
end

# app/api/proj/api/v2/entities/committee_list.rb
module PROJ::API::V2::Entities
  class CommitteeList < CommitteeBase; end
end

Note that in this example I have renamed some things; your class names should be singular (committee not committees) and the filenames should match them, but making that change may cause other issues in your app. Generally, you should use singular and not plural.

I recommend reading the Rails guide entry on constants and autoloading for more detail.

Updated:

In your gist you say that you get Uninitialized constant PROJ::API::V2::Entities::CommitteeOffice when you run present @committees, with: PROJ::API::V2::Entities::CommitteeOffice with the following code:

# app/api/proj/api/v2/entities/committee_base.rb
module PROJ::API::V2::Entities
  class CommitteeBase < Grape::Entity; 
    expose :id
  end
  class CommitteeOffice < CommitteeBase; 
    expose :name
  end
end

You get this error because Rails will only look for the class named PROJ::API::V2::Entities::CommitteeBase in the file entities/committee_base.rb. If you prefer to use a single monolithic file for your entity classes, then you must name the above file app/api/proj/api/v2/entities.rb.

By naming the file app/api/proj/api/v2/entities.rb, it tells Rails "This file contains the module Entities and all its classes."

Finecut answered 17/4, 2017 at 18:43 Comment(2)
With the file structure its working fine for me, but if i have structure like this its not working gist.github.com/anbublacky/a6e66217b2fcdeb52fe580864beecf7fLaryssa
Updated answer based on gistFinecut

© 2022 - 2024 — McMap. All rights reserved.