rbexy
rbexy copied to clipboard
Local-scoped components
Hello! First of all, thanks so much for building this project. I've always wanted to have this kind of template in Ruby/Rails, and it's amazing to see this library implementing it.
I'm currently evaluating using it in a personal project, but one feature that I couldn't find in Rbexy and that I think is very interesting is the ability to define local-scoped components, just like React allows you to define multiple function components in a file, and like Phoenix LiveView also allows doing with functional components.
Sometimes, a component, or a view, is made of smaller subcomponents that are not supposed to be global throughout the application. Global components promote reusability, but lots of times a component is not meant to be reusable. The issues I think we have with everything being global by default are:
-
We need to be more careful to avoid name clashes, and sometimes create very specific namespaces
-
Too many files for defining a component, and lots of indirection and jumping around
-
Global components promote reusability and sometimes making something reusable/abstracted too soon results in a complex component that addresses too many use cases (by receiving different options). Early abstractions are often bad.
Allowing multiple components to be defined in a single file and making them locally scoped would help address those points. I think this would require allowing the template to be defined inside the ruby file itself, which also has some challenges around code highlighting.
What do you think of the idea? Is this something that was already considered in the development of Rbexy?
@guisehn Hey! This is a great idea. I think this is more-or-less already doable in a couple of different ways, but perhaps could have some syntactic sugar added to make it a little nicer to do so:
Option 1: namespaced component classes
class RootComponent < Rbexy::Component
class SubComponent < Rbexy::Component
end
end
Templates would be root_component.rbx
and root_component/sub_component.rbx
Technically SubComponent
is still globally available as <RootComponent.Sub />
but I think the naming being within the RootComponent
namespace makes the intention clear.
Option 2: manually render sub-templates
class RootComponent < Rbexy::Component
def sub
Rbexy.evaluate("<div>Some sub-template here</div>", self)
end
end
And in root_component.rbx
template:
<div>
<h1>Root component</h1>
{sub}
</div>
You could use a heredoc for longer templates:
class RootComponent < Rbexy::Component
def sub
Rbexy.evaluate(<<-RBX, self)
<div>
<p>Some more complicated template here</p>
</div>
RBX
end
end
I haven't tested any of this but I think it's all possible. Curious to hear your thoughts.