Module: Ruflet::UI::ControlFactory

Defined in:
lib/ruflet_ui/ruflet/ui/control_factory.rb

Constant Summary collapse

CLASS_MAP =
Controls::RufletControls::CLASS_MAP
.merge(Services::RufletServices::CLASS_MAP)
.freeze

Class Method Summary collapse

Class Method Details

.build(type, id: nil, **props) ⇒ Object

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ruflet_ui/ruflet/ui/control_factory.rb', line 17

def build(type, id: nil, **props)
  normalized_type = type.to_s.downcase
  if ENV["RUFLET_DEBUG"] == "1" && normalized_type == "floatingactionbutton"
    Kernel.warn("[factory] type=#{normalized_type} id=#{id.inspect} props=#{props.inspect}")
  end
  klass = CLASS_MAP[normalized_type]
  if klass
    normalized_props = normalize_constructor_props(klass, props)
    if ENV["RUFLET_DEBUG"] == "1" && normalized_type == "floatingactionbutton"
      Kernel.warn("[factory] normalized_props=#{normalized_props.inspect}")
    end
    return klass.new(id: id, **normalized_props)
  end

  raise ArgumentError, "Unknown control type: #{normalized_type}"
end

.constructor_keywords(klass) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/ruflet_ui/ruflet/ui/control_factory.rb', line 49

def constructor_keywords(klass)
  klass.instance_method(:initialize).parameters
       .select { |kind, _| kind == :key || kind == :keyreq }
       .map { |_, name| name }
       .reject { |name| name == :id }
rescue StandardError
  []
end

.normalize_constructor_props(klass, props) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/ruflet_ui/ruflet/ui/control_factory.rb', line 34

def normalize_constructor_props(klass, props)
  keywords = constructor_keywords(klass)
  return props if keywords.empty?

  allowed = keywords.map(&:to_s)
  mapped = props.each_with_object({}) { |(k, v), out| out[k.to_sym] = v }
  if mapped.key?("value") && !allowed.include?("value") && allowed.include?("text") && !mapped.key?("text")
    mapped["text"] = mapped.delete("value")
  end
  if mapped.key?(:value) && !allowed.include?("value") && allowed.include?("text") && !mapped.key?(:text)
    mapped[:text] = mapped.delete(:value)
  end
  mapped
end