我可以使用类似 String#constantize 的东西来初始化 Hyperstack::Component 吗?

Can I use something along the lines of String#constantize to initialize a Hyperstack::Component?

我的数据库中有一些对象,我想使用专用的 Hyperstack 视图组件来呈现这些对象。 假设我的对象从 A 到 J 有一个唯一的 name 属性。现在我想用 each 遍历它们并渲染 ComponentA, ComponentB , ComponentC, ... 取决于我对象的 name ,并将我的对象作为参数传递给组件。

我现在做的是:

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

这是伪代码,因为您不能给变量进行常量化。 但它显示了我想做的事情。

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

从未使用过 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 将 return 实际常量,而不仅仅是一个常量化的字符串(驼峰式等等),因此您可以调用 #new#call 或者你想要的任何东西。

每个组件 class 都定义了一个与 class 同名的方法。例如,当您说

ComponentA(data: object)

您正在调用名为 ComponentA 的方法,该方法与 ComponentA class.

相关联

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

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

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

('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 以外的东西。无论如何,你真的可以玩得开心!