rubymonolith / superform

Build highly customizable forms in Rails
MIT License
263 stars 14 forks source link

Collection namespaces use Superform::Field instead of ApplicationForm::Field #7

Open dhnaranjo opened 8 months ago

dhnaranjo commented 8 months ago
class PageForm < ApplicationForm
  def template
    div do
      field(:id).input
      collection(:responses).each do |response_fields|
        response_fields.field(:option_id).input
      end
    end
  end
end

The call to field(:id) returns an instance of ApplicationForm::Field, while the one inside the collection returns Superform::Field, so input and all my custom fields are unavailable.

My stupid hack is to monkeypatch Superform::Namespace.

module Superform
  class Namespace < Node
    def initialize(key, parent:, object: nil, field_class: ApplicationForm::Field)
      super(key, parent:)
      @object = object
      @field_class = field_class
      @children = {}
      yield self if block_given?
    end
  end
end

You got a better idea of how to handle this?

bradgessler commented 7 months ago

It looks like the collection method is passing a NamespaceCollection constant into the create_child method, which doesn't pass the reference to the class you've extended.

Here's the code that I think has the bug: https://github.com/rubymonolith/superform/blob/150985cc28a3d4888c12ea7c5b5109635d9d4870/lib/superform.rb#L140-L144

dhnaranjo commented 7 months ago
module NamespacePatch
  def collection(key, &)
    create_child(key, Superform::NamespaceCollection, field_class: @field_class, &)
  end
end

module NamespaceCollectionPatch
  def initialize(*, field_class:, **, &)
    @field_class = field_class
    super(*, **, &)
  end

  def build_namespace(index, **)
    parent.class.new(index, parent: self, field_class: @field_class, **, &@template)
  end
end

This gets it where it needs to be. Want a PR?

bradgessler commented 7 months ago

Want a PR?

Heck yeah!