phlex
phlex copied to clipboard
Shorter `component` method
It might be worth either renaming the component
method or giving it a short alias. A few options that come to mind:
-
comp
,com
or evenc
-
render
ordraw
-
view
Another option might be to define a method for each component class name, like the Array()
method.
def template
NavComponent {
Nav::ItemComponent "Home", "/"
Nav::ItemComponent "About", "/about"
Nav::ItemComponent "Contact", "/contact"
}
end
One downside with this is you would need to use an empty set of parens if you weren't passing any arguments or blocks to the component.
def template(&)
head { ... }
body {
HeaderComponent()
content(&)
FooterComponent()
}
end
I think this is my favourite option so far — it looks and feels really nice — but I’m open to other suggestions.
I'm not sure how performant it is, but you should be able to define const_missing
on the Phlex::Component
class such that:
def template(&)
head { ... }
body {
HeaderComponent
content(&)
FooterComponent
}
end
could work (with const_missing
taking the name of the constant, getting the class object, and then calling ()
on it).
However, if that noticeably hurts performance, Component()
or Component[]
isn't bad.
I’m pretty sure it won't be missing though as the constant will exist.
Ah. I was presuming that Ruby would sort-of walk up the lexical scopes, and so if Bar
was defined on the global scope, but called within a method inside of Foo
, then Foo.const_missing
would be called before then finding Bar
in the next scope up.
However, I just did a quick test in a console and that isn't true. Disregard.
@alexandreruban and I worked on this and got it basically finished before we realised Symbols (and method names) can't contain :
.
I wonder if we should do this to stay really consistent with ViewComponent and ActionView. I also like that you don't have to discount the first positional argument like you do with component MyComponent, actually_first_argument
.
def template
render NavComponent.new {
render Nav::ItemComponent.new("Home", "/")
render Nav::ItemComponent.new("About", "/about")
render Nav::ItemComponent.new("Contact", "/contact")
}
end
I expect removing the splat and the additional block.binding.receiver
check would improve performance too.
I tried the above and it didn't work because we can't easily capture the context for the Phlex::Block. Let's just stick with component
for now.