- Typed Attributes: Runtime checked typed Attributes (based on ActiveModel)
- VC: View Components for Rails
- What is next?
I have a number of gems released (or planned to be).
This page shows the collection of Ruby gems, including examples of usage.
Typed Attributes
: Runtime checked typed Attributes (based on ActiveModel
)
Define instance attribute accessors with expected data type information, default values and coercion:
attr_string :tag, default: "div", convert: true
attr_string :label, allow_nil: false
attr_symbol :variant, default: :contained, in: [:contained, :raised, :outlined, :text]
attr_array :scores, sub_type: Numeric, convert: true
VC
: View Components for Rails
Sound familiar? In 2018, before the release of Joel Hawksley’s view_component I built my own ViewComponent
implementation. Over the course of the next 2 years it evolved and grew to be very feature complete.
While I now highly recommend view_component you might be interested to compare with what I have here.
Renamed as VC
: encapsulating views into testable, reusable entities that play nicely with the Rail additionally with:
- attributes or ‘props’ of views can be validated and have their types checked
- DSL is provided for working with
Stimulus
- RSpec shared examples and support for fuzz testing view components
- play nicely with the Rails Russian doll view caching mechanism
Example Component
class Avatar < ::VC
auto_cache(true)
attr_string :image_url
attr_string :initials
validates_length_of :initials, minimum: 1, maximum: 3, allow_blank: true
attr_symbol :shape, in: [:circle, :square], default: :circle
attr_symbol :size, in: [:tiny, :small, :medium, :large, :extra_large], default: :medium
def element_classes
[
"vc-avatar",
"vc-avatar--#{shape}",
"vc-avatar--#{shape}--#{size}"
]
end
end
<%= view_component_tag component do %>
<% if component.image_url? %>
<%= image_tag component.image_url %>
<% else %>
<p><%= component.initials %></p>
<% end %>
<% end %>
Testing a Component
RSpec.describe ::Avatar, type: :view do
# Check each parameter combination
it_behaves_like(
"a view component",
attributes: {
image_url: {
valid: ["https://cataas.com/cat/says/hello", nil],
invalid: ["not_a_valid_asset"]
},
initialsZ: {
valid: ["A", "AB", "A B"],
invalid: ["AB C", 123]
}
},
)
# Checks the specific component instance will render
it_behaves_like(
"a rendered view component",
component: described_class.new(initials: "A B", url: "http://image_url"),
content_to_match: %r{src="http:\/\/image_url},
)
# More custom render tests
describe "#render" do
it "does not render successfully with invalid initials length" do
expect {
described_class.new(initials: "AB C").render(view_context: view)
}.to raise_error ActiveModel::ValidationError
end
end
end
What is next?
For each of these gems I plan to write a post about them and discuss how they might be useful while they compare to alternatives out there.
I also plan to do some deep dives into the how’s and whys of some of the limitations for both these gems and alternatives.
Read more • open-source • Ruby