I have a common pattern or repeated code that I'd like to DRY up in my ActiveAdmin views. I'm using arbre components to render as much of my views as I can and I'd like to keep it that way if possible (i.e. I don't really want to convert to straight up HTML in the normal fashion -- I'm trying to understand the arbre way here). Here's the code I'd like to DRY up:
clients.in_groups_of(3).each do |clients_group|
columns do
clients_group.compact.each do |client|
column do
panel client.name do
# ...
end
end
end
end
end
After reading through the documentation in the arbre gem, I started to try to create my own, custom arbre component. But I was quickly forced to realize that I have no idea how to satisfy arbre. I couldn't figure out how to pass my local variables into the block. For example:
# config/initializers/active_admin.rb
module ActiveAdmin
module Views
class ClientsBreakdown < ActiveAdmin::Component
builder_method :clients_breakdown
def build(clients, attributes = {})
group_size = attributes.delete(:in_groups_of) { 3 }
clients.in_groups_of(group_size).each do |clients_group|
columns do
clients_group.compact.each do |client|
column do
panel client.name do
super(attributes) # Doesn't seem to matter where this `super` call
# is, but I do want to be able to pass `client`
# into the `clients_breakdown` block here
# yield(client) # -- I've also tried adding this.
end
end
end
end
end
end
end
end
end
Then, calling this in my ActiveAdmin User view might look like:
clients_breakdown(Client.all, in_groups_of: 2) do |client|
ul do
li client.name
end
end
Running the above code results in this error:
UPDATE 2 The exception has changed to this after moving my custom component code into the ActiveAdmin::Views
module.
My key issue seems to be that I can't just call yield(client)
where I currently have super(attributes)
. But that's an arbre thing so I don't know what to do there to pass the client into the calling block. Is this the right track or is there another way to DRY this up?
UPDATE 1
I've realized that the call to super
can happen anywhere in the build
method and really has nothing to do with what is output. So even if I move the super(attributes)
call up... I still can't figure out what to put inside of the panel
block so that I can render the rest of my arbre components in there from the call to clients_breakdown
.
Here is one potential solution.
A few things to note are
super(attributes)
should not be called unless theClientBreakdown
Arbre component is outputting its own HTML. Arbre components are generally used to build up HTML from scratch, not necessarily to compose components.Another approach would be to define helper methods to provide the same functionality in a module to be included in
ActiveAdmin::Views::Pages::Base
. This is where ActiveAdmin defines its helper methods to build the various views, likeattributes_table
.