ErbComponent
Why not have view components and write them in OOP style? It hides complexity. DRYes views.
FEEL FREE TO OPEN AN ISSUE OR HAVE SOME DISCUSSION.
USE WITH CAUTION! This is more like an experiment.
Installation
Add this line to your application's Gemfile:
gem 'erb_component'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install erb_component
Usage
Easiest example
It's important to define template
method
class ImgTag < ErbComponent
attr_reader :src
# req is Rack::Request or ActionDispatch::Request (for Rails)
def initialize(req, opts)
@src = opts[:src]
super
end
def template
<<ERB
<img src="<%= src %>" />
ERB
end
end
# Somewhere in views:
url = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Ruby_logo.svg/1920px-Ruby_logo.svg.png"
ImgTag.(request, src: url) # or ImgTag.new(request, src: url).call
# => "<img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Ruby_logo.svg/1920px-Ruby_logo.svg.png\" />\n"
You can use more elegant Rails content_tag
class ImgContentTag < ErbComponent
attr_reader :src
def initialize(req, opts)
@src = opts[:src]
super
end
def template
content_tag :img, nil, src: src
end
end
More advanced nested example
Here TabNavs.(request, tab_list: %w(overview photos contact accommodations))
will generate Bootstrap's tab navigation, like here: https://getbootstrap.com/docs/5.0/components/navs-tabs/
class TabNavs < ErbComponent
attr_reader :tab_list
def initialize(req, tab_list:)
@tab_list = tab_list
super
end
def template
<<ERB
<ul class="nav nav-tabs" id="myTab" role="tablist">
<%= tab_list_rendered %>
</ul>
ERB
end
def tab_list_rendered
active_found = false
opts = tab_list.map do |i|
if params[:active_tab] == i
active_found = true
{target: i, active: true}
else
{target: i, active: false}
end
end
opts[0][:active] = true unless active_found
opts.map do |i|
NavItem.(req, **i)
end.join("\n")
end
end
class NavItem < ErbComponent
attr_reader :target
def initialize(req_params, active: false, target:)
@req_params = req_params
@active = active
@target = target
super
end
def template
<<ERB
<li class="nav-item" role="presentation">
<button class="<%= button_class %>" id="<%= id %>" data-bs-toggle="tab" data-bs-target="#<%= target %>" type="button" role="tab" aria-controls="<%= target %>" aria-selected="true">
<%= tab_name %>
</button>
</li>
ERB
end
def id
"#{target}-tab"
end
def tab_name
target.humanize
end
def button_class
res = "nav-link"
res += " active" if active?
res
end
def active?
@active
end
end
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/arthurkarganyan/erb_component.
License
The gem is available as open source under the terms of the MIT License.