I am building Grape Entities inside my Rails models as described here:
https://github.com/ruby-grape/grape-entity#entity-organization
Currently I am creating default values automatically, based on the column hash of the model itself.
So I have a static get_entity method that exposes all the model's columns:
class ApplicationRecord < ActiveRecord::Base
def self.get_entity(target)
self.columns_hash.each do |name, column|
target.expose name, documentation: { desc: "Col #{name} of #{self.to_s}" }
end
end
end
And then I have here an example Book model using it inside the declared Entity subclass (the comment also shows how I can override the documentation of one of the model's column):
class Book < ActiveRecord::Base
class Entity < Grape::Entity
Book::get_entity(self)
# expose :some_column, documentation: {desc: "this is an override"}
end
end
The downside with this approach is that I always need to copy and paste the class Entity declaration in each model I want the Entity for.
Can anybody help me out generating the class Entity for all child of ApplicationRecord automagically? Then if I need overrides I will need to have the Entity declaration in the class, otherwise if the default declaration is enough and can leave it as it is.
NOTE:
I cannot add class Entity definition straight inside ApplicationRecord because, Entity class should call get_entity and get_entity depends on column_hash of Books.
SOLUTION:
ended up doing this thanks to brainbag:
def self.inherited(subclass)
super
# definition of Entity
entity = Class.new(Grape::Entity)
entity.class_eval do
subclass.get_entity(entity)
end
subclass.const_set "Entity", entity
# definition of EntityList
entity_list = Class.new(Grape::Entity)
entity_list.class_eval do
expose :items, with: subclass::Entity
expose :meta, with: V1::Entities::Meta
end
subclass.const_set "EntityList", entity_list
end
def self.get_entity(entity)
model = self
model.columns_hash.each do |name, column|
entity.expose name, documentation: { type: "#{V1::Base::get_grape_type(column.type)}", desc: "The column #{name} of the #{model.to_s.underscore.humanize.downcase}" }
end
end
Thanks!