1

我的数据库中有一些对象,我喜欢使用专用的 Hyperstack 视图组件进行渲染。假设我的对象具有name从 A 到 J 的唯一属性。现在我想循环它们并根据我的对象的, , , ...each渲染它们,并将我的对象作为参数传递给组件。ComponentAComponentBComponentCname

我现在要做的是:

DB_Objects.each do |object|
  if    object.name == 'A'
    ComponentA(data: object)
  elsif object.name == 'B'
    ComponentB(data: object)
  elsif object.name == 'C'
    ComponentC(data: object)
  elsif ...

我想做的是:

DB_Objects.each do |object|
  ('Component' + object.name).constantize(data: object)
end

这是伪代码,因为你不能给变量常量化。但它显示了我想做什么。

如何防止手动将对象映射到其视图。

4

2 回答 2

2

从未使用过 HyperStack,但这应该会给您正确的想法。

class Thing < ApplicationRecord
  OBJECT_TYPES = { 'A': 'CommponentA' }.freeze

  def to_component
    @to_component ||= OBJECT_TYPES[self.name].constantize.new(self)
  end 
end 

你可以,"Component#{self.name}".constantize.new(self)但我发现当其他开发人员加入一个项目时,这会让他们相当困惑。

请记住,String#constantize将返回实际的常量,而不仅仅是一个常量化的字符串(camelcased 和你有什么),所以你可以调用它#new#call你想要的任何东西。

于 2019-08-03T22:32:25.617 回答
1

每个组件类都定义了一个与该类同名的方法。当你说例如

ComponentA(data: object)

您正在调用一个ComponentA与 ComponentA 类绑定的名为的方法。

因此,要动态引用组件,您将使用以下send方法:

send('Component' + object.name, data: object)

或者,每个组件类都有一个类方法insert_element,该方法将渲染组件类的实例,并将其插入渲染缓冲区。例如:

('Component' + object.name).constantize.insert_element(data: object)

我提出这个是因为虽然它更长,但你可以用它来概括你的这个想法(我认为这很酷)

class ApplicationRecord < ActiveRecord::Base
  def render(opts = {})
    ('Component' + object.name).constantize.insert_element(opts, data: object)
  end
end

现在你可以说

some_record.render

当然,要像这样概括它,您可能想要使用name. 无论如何,你真的可以玩得开心!

于 2019-08-03T23:29:08.600 回答