从父类继承类定义 [英] Inheriting class definition from parent class
问题描述
我正在Rails模型中构建葡萄实体,如下所述:
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.
所以我有一个静态的get_entity方法,该方法公开了模型的所有列:
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
然后在这里有一个示例Book模型,在已声明的Entity子类中使用它(注释也显示了如何覆盖模型列之一的文档):
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
这种方法的缺点是,我总是需要在要为其创建实体的每个模型中复制并粘贴类Entity声明.
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.
有人可以帮我为ApplicationRecord的所有子代自动生成类Entity吗?然后,如果需要重写,则需要在类中具有Entity声明,否则,如果默认声明足够并且可以保留原样.
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.
注意:
我不能直接在ApplicationRecord内部添加类Entity定义,因为Entity类应调用get_entity,而get_entity取决于Books的column_hash.
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.
解决方案:
由于脑袋而结束了这项工作:
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
谢谢!
推荐答案
我没有使用Grape,所以这里可能有一些我不知道的额外魔术,但这在Ruby中很容易做到/路轨.根据您的问题自动为ApplicationRecord的所有子类生成类Entity",您可以执行以下操作:
I haven't used Grape so there may be some extra magic here that you need that I don't know about, but this is easy to do in Ruby/Rails. Based on your question "generating the class Entity for all child of ApplicationRecord automagically" you can do this:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
class Entity < Grape::Entity
# whatever shared stuff you want
end
end
然后图书将可以访问父级Entity
:
Book will then have access to the parent Entity
:
> Book::Entity
=> ApplicationRecord::Entity
如果只想向Book::Entity
添加额外的代码,则可以在Book
中将其子类化,如下所示:
If you want to add extra code only to the Book::Entity
, you can subclass it in Book
, like this:
class Book < ApplicationRecord
class Entity < Entity # subclasses the parent Entity, don't forget this
# whatever Book-specific stuff you want
end
end
然后Book::Entity
将是其自己的类.
> Book::Entity
=> Book::Entity
要将此与需要在继承的类上调用get_entity
的需求相结合,可以使用#inherited
方法在ApplicationRecord
被子类化的任何时间自动调用get_entity
:
To combine this with your need for get_entity
to be called on an inherited class, you can use the #inherited
method to automatically call get_entity
any time ApplicationRecord
is subclassed:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def self.get_entity(target)
target.columns_hash.each do |name, column|
target.expose name, documentation: { desc: "Col #{name} of #{self.to_s}" }
end
end
def self.inherited(subclass)
super
get_entity(subclass)
end
class Entity < Grape::Entity
# whatever shared stuff you want
end
end
这篇关于从父类继承类定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!