Inheritance
As you start to accumulating more components in your application, you’ll natrually find yourself wanting to make little tweaks in different areas. There’s several strategies to managing these tweaks including intialization parameters, extended classes, and composition.
Initialization parameters
One way of handling slight varations to a component is by passing arguments into it upon initialization. This example shows how to change the size of a card compone.t
class MyCard < Component::Base
def initialize(size: :small)
@size = size
end
def view_template
div(class: ["card", "card__#{@size}"]){
yield
}
end
end
You might call the variants like this:
<%= render MyCard.new(size: :large) do %>
<h1>Large Card</h1>
<% end %>
<%= render MyCard.new(size: :small) do %>
<h1>Small Card</h1>
<% end %>
One problem with this approach is a user might pass the wrong argument into the initializer, which means you’d have to add validation to check the size.
<%= render MyCard.new(size: "blue") do %>
<h1>Large Card</h1>
<% end %>
You could add validation logic to the initialize to check the size, but that adds a fair amount of code for not much benefit. Instead, consider extracting it out into its own component.
Variations via class inheritance and endless methods
Instead of passing a size parameter into a componet, we can use inheritence and lean on Ruby to handle it for us.
module MyCard
class Base < Component::Base
def size = :small
def view_template
div(class: ["card", "card__#{size}"]){
yield
}
end
end
# For consistency
Small = Base
class Medium < Base
def size = :medium
end
class Large < Base
def size = :large
end
end
Here’s what it looks like when rendering each from Erb.
<%= render MyCard::Large.new do %>
<h1>Large Card</h1>
<% end %>
<%= render MyCard::Small.new do %>
<h1>Small Card</h1>
<% end %>
When a developer tries to render a card with an invalid size, an error will be raised that MyCard::Blue doesn’t exist.
<%= render MyCard::Blue.new do %>
<h1>Large Card</h1>
<% end %>
Since Phlex is just Ruby, we can use Ruby’s constant lookup to handle this for us which means less code for us to write and test, and better error messages for developers using the components.
