heartcombo/simple_form · error · NotImplementedError

input should be implemented by classes inheriting from Colle

Error message

input should be implemented by classes inheriting from CollectionInput

What it means

CollectionInput is the abstract base for inputs rendered from a collection (selects, radio buttons, check boxes); it supplies collection and option plumbing, and its #input deliberately raises NotImplementedError so concrete subclasses (CollectionSelectInput, CollectionRadioButtonsInput, ...) must override it (lib/simple_form/inputs/collection_input.rb:18). Any custom input that inherits from CollectionInput without defining #input hits this stub at render time.

Source

Thrown at lib/simple_form/inputs/collection_input.rb:18

# frozen_string_literal: true
module SimpleForm
  module Inputs
    class CollectionInput < Base
      BASIC_OBJECT_CLASSES = [String, Integer, Float, NilClass, Symbol, TrueClass, FalseClass]
      BASIC_OBJECT_CLASSES.push(Fixnum, Bignum) unless 1.class == Integer

      # Default boolean collection for use with selects/radios when no
      # collection is given. Always fallback to this boolean collection.
      # Texts can be translated using i18n in "simple_form.yes" and
      # "simple_form.no" keys. See the example locale file.
      def self.boolean_collection
        [ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
          [I18n.t(:"simple_form.no", default: 'No'), false] ]
      end

      def input(wrapper_options = nil)
        raise NotImplementedError,
          "input should be implemented by classes inheriting from CollectionInput"
      end

      def input_options
        options = super

        options[:include_blank] = true unless skip_include_blank?
        translate_option options, :prompt
        translate_option options, :include_blank

        options
      end

      private

      def collection
        @collection ||= begin
          collection = options.delete(:collection) || self.class.boolean_collection

View on GitHub (pinned to 18f38aad0b)

Solutions

  1. Implement the method in the subclass: def input(wrapper_options = nil) ... end, typically delegating to @builder.collection_select/collection_radio_buttons with input_options and input_html_options
  2. Prefer inheriting from a concrete class such as CollectionSelectInput and overriding only the parts you need
  3. If the input is not actually collection-based, inherit from SimpleForm::Inputs::Base or StringInput instead

Example fix

# before
class StarInput < SimpleForm::Inputs::CollectionInput
  # no #input defined -> NotImplementedError at render
end

# after
class StarInput < SimpleForm::Inputs::CollectionInput
  def input(wrapper_options = nil)
    @builder.collection_select(
      attribute_name, collection, value_method, label_method,
      input_options, input_html_options
    )
  end
end
Defensive patterns

Strategy: validation

Validate before calling

# fail fast at boot/test instead of mid-render
def implements_own_input?(klass)
  klass.instance_method(:input).owner != SimpleForm::Inputs::CollectionInput
end

raise NotImplementedError, "#{TagInput} must implement #input" unless implements_own_input?(TagInput)

Prevention

When it happens

Trigger: class TagInput < CollectionInput; end registered via SimpleForm::FormBuilder.map_type :tag, to: TagInput or selected with as: :tag, then rendered; naming the method render or to_html instead of input; instantiating CollectionInput itself.

Common situations: Writing a custom select-like input and inheriting the wrong base class; upgrading simple_form where the abstract contract got stricter; copy-pasting an old custom input skeleton that stopped working.

Related errors


AI-assisted analysis of heartcombo/simple_form@18f38aad0b (2026-08-21). Data as JSON: /api/errors/22b35f43702c7b99. Report an issue: GitHub.