从父 class 继承 class 定义
Inheriting class definition from parent class
我正在我的 Rails 模型中构建葡萄实体,如下所述:
https://github.com/ruby-grape/grape-entity#entity-organization
目前我正在根据模型本身的列哈希自动创建默认值。
所以我有一个公开模型所有列的静态 get_entity 方法:
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 模型,在声明的实体子 class 中使用它(评论还显示了我如何覆盖模型列之一的文档):
class Book < ActiveRecord::Base
class Entity < Grape::Entity
Book::get_entity(self)
# expose :some_column, documentation: {desc: "this is an override"}
end
end
这种方法的缺点是我总是需要在我想要实体的每个模型中复制并粘贴 class 实体声明。
谁能帮我自动为 ApplicationRecord 的所有子项生成 class 实体?然后,如果我需要覆盖,我将需要在 class 中包含实体声明,否则如果默认声明足够并且可以保持原样。
注意:
我不能直接在 ApplicationRecord 中添加 class 实体定义,因为实体 class 应该调用 get_entity 而 get_entity 取决于 Books 的 column_hash。
解决方案:
多亏了脑袋,最终做到了这一点:
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/Rails 中很容易做到。根据你的问题"generating the class Entity for all child of ApplicationRecord automagically"你可以这样做:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
class Entity < Grape::Entity
# whatever shared stuff you want
end
end
Book 将可以访问父 Entity
:
> Book::Entity
=> ApplicationRecord::Entity
如果你只想向 Book::Entity
添加额外的代码,你可以在 Book
中子class它,像这样:
class Book < ApplicationRecord
class Entity < Entity # subclasses the parent Entity, don't forget this
# whatever Book-specific stuff you want
end
end
那么Book::Entity
就是自己的class.
> Book::Entity
=> Book::Entity
为了将此与您需要在继承的 class 上调用 get_entity
相结合,您可以随时使用 #inherited
方法自动调用 get_entity
ApplicationRecord
是 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
我正在我的 Rails 模型中构建葡萄实体,如下所述:
https://github.com/ruby-grape/grape-entity#entity-organization
目前我正在根据模型本身的列哈希自动创建默认值。
所以我有一个公开模型所有列的静态 get_entity 方法:
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 模型,在声明的实体子 class 中使用它(评论还显示了我如何覆盖模型列之一的文档):
class Book < ActiveRecord::Base
class Entity < Grape::Entity
Book::get_entity(self)
# expose :some_column, documentation: {desc: "this is an override"}
end
end
这种方法的缺点是我总是需要在我想要实体的每个模型中复制并粘贴 class 实体声明。
谁能帮我自动为 ApplicationRecord 的所有子项生成 class 实体?然后,如果我需要覆盖,我将需要在 class 中包含实体声明,否则如果默认声明足够并且可以保持原样。
注意:
我不能直接在 ApplicationRecord 中添加 class 实体定义,因为实体 class 应该调用 get_entity 而 get_entity 取决于 Books 的 column_hash。
解决方案:
多亏了脑袋,最终做到了这一点:
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/Rails 中很容易做到。根据你的问题"generating the class Entity for all child of ApplicationRecord automagically"你可以这样做:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
class Entity < Grape::Entity
# whatever shared stuff you want
end
end
Book 将可以访问父 Entity
:
> Book::Entity
=> ApplicationRecord::Entity
如果你只想向 Book::Entity
添加额外的代码,你可以在 Book
中子class它,像这样:
class Book < ApplicationRecord
class Entity < Entity # subclasses the parent Entity, don't forget this
# whatever Book-specific stuff you want
end
end
那么Book::Entity
就是自己的class.
> Book::Entity
=> Book::Entity
为了将此与您需要在继承的 class 上调用 get_entity
相结合,您可以随时使用 #inherited
方法自动调用 get_entity
ApplicationRecord
是 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