Skip to content

Instantly share code, notes, and snippets.

@bradgessler
Last active August 21, 2025 00:23
Show Gist options
  • Select an option

  • Save bradgessler/f10cc44695e1a50ef9c4d88be5168995 to your computer and use it in GitHub Desktop.

Select an option

Save bradgessler/f10cc44695e1a50ef9c4d88be5168995 to your computer and use it in GitHub Desktop.
Superform kits
# frozen_string_literal: true
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "phlex"
end
require "phlex"
module Alpha
module Superform
module Kit
def self.extended(mod)
# define helpers for already-present constants in this namespace
mod.constants.each { |name| mod.__define_kit_method__(name) }
end
# Fires whenever a constant is defined directly under the module
def const_added(name)
__define_kit_method__(name)
super
end
# protected
# Define the instance helper once per constant (idempotent)
def __define_kit_method__(name)
define_method name do |key, *args, **kwargs, &block|
klass = self.class.const_get(name) # reload-safe lookup
component = klass.new(field(key), *args, **kwargs)
render(component, &block)
end
end
end
module Fields
class Base
def initialize(field)
end
end
Input = Base
class Select < Base
def initialize(field, collection)
@collection = collection
end
end
end
end
class Form
module Fields
include Superform::Fields
extend Superform::Kit
# Define your input fields here...
end
def render(field)
puts "Rendering field #{field.inspect}"
end
def field(key)
puts "Field #{key}"
end
include Fields
end
Form.new.tap do |form|
form.Input(:name)
form.Select(:age, 1..100)
end
end
module Beta
class Input
def initialize(...)
end
end
class Form
def render(component)
puts "Rendering #{component.inspect}"
end
def field(key)
p key
end
def self.field(name)
define_method("#{name}_field") do |key, *args, **kwargs, &block|
render self.send(name, field(key), *args, **kwargs, &block)
end
end
field def input(key, *, **)
Input.new(field(key), *, **)
end
end
Form.new.tap do |form|
form.input_field(:name)
form.input(:email, type: :email)
end
end
module Gamma
class Input
def initialize(field, **)
@field = field
end
end
class Form
class Field
attr_accessor :key
def initialize(key, form)
@key = key
@form = form
end
def input(**)
@form.render Input.new(self, **)
end
end
def field(key)
Field.new(key, self)
end
def render(component)
puts "Rendering #{component.inspect}"
end
end
Form.new.tap do |form|
form.field(:name).input
form.field(:email)
end
end
module Delta
class Input < Phlex::HTML
def initialize(field, **)
@field = field
end
def view_template
input(type: :text, name: @field.key)
end
end
class Form
class Field
attr_accessor :key
def initialize(key)
@key = key
end
class Kit
def initialize(field, form)
@field = field
@form = form
end
end
def self.method_added(name)
self::Kit.define_method(name) do |*args, **kwargs, &block|
instance = @field.send(name, *args, **kwargs, &block)
raise "#{instance} is not a Phlex component" unless instance.is_a?(Phlex::HTML)
@form.render instance
end
end
def input(**)
Input.new(self, **)
end
end
def field(key)
self.class::Field.new(key)
end
def Field(key)
self.class::Field::Kit.new(field(key), self)
end
def render(component)
puts "Rendering #{component.call}"
end
end
Form.new.tap do |form|
form.Field(:name).input
form.render form.field(:phone).input
end
class MyForm < Form
class Field < Field
def my_input(**)
Input.new(self, **)
end
end
end
MyForm.new.tap do |form|
form.Field(:first_name).my_input
form.Field(:last_name).input
form.render form.field(:email).my_input
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment