ruby-on-railsrubyreactjsisomorphichyperstack

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


I have some objects in my DB that I like to render with a dedicated Hyperstack view Component. Lets say my objects have a unique name property from A to J. Now I would like to loop through them with each and render a ComponentA, ComponentB, ComponentC, ... depending on the name of my object, and pass my object as a param to the component.

What I do now is:

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 ...

What I want to do is something like:

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

This is pseudo code as you can't give variables to constantize. But it shows what I would like to do.

How can I prevent a manual mapping of a object to its view.


Solution

  • Every component class defines a method of the same name as the class. When you say for example

    ComponentA(data: object)
    

    you are calling a method named ComponentA that is tied the the ComponentA class.

    So to dynamically reference the component you would use the send method:

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

    Alternatively each component class has a class method insert_element which will render an instance of the component class, and insert it into the rendering buffer. For example:

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

    I bring this up because while it is longer, you could use it to generalize this idea of yours (which I think is pretty cool)

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

    Now you can say

    some_record.render
    

    Of course to generalize it like this you might want to use something other than name. Anyway you could really have fun with this !