{"record":{"id":"22b35f43702c7b99","repo":"heartcombo/simple_form","slug":"input-should-be-implemented-by-classes-inheriting","errorCode":null,"errorMessage":"input should be implemented by classes inheriting from CollectionInput","messagePattern":"input should be implemented by classes inheriting from CollectionInput","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"lib/simple_form/inputs/collection_input.rb","lineNumber":18,"sourceCode":"# frozen_string_literal: true\nmodule SimpleForm\n  module Inputs\n    class CollectionInput < Base\n      BASIC_OBJECT_CLASSES = [String, Integer, Float, NilClass, Symbol, TrueClass, FalseClass]\n      BASIC_OBJECT_CLASSES.push(Fixnum, Bignum) unless 1.class == Integer\n\n      # Default boolean collection for use with selects/radios when no\n      # collection is given. Always fallback to this boolean collection.\n      # Texts can be translated using i18n in \"simple_form.yes\" and\n      # \"simple_form.no\" keys. See the example locale file.\n      def self.boolean_collection\n        [ [I18n.t(:\"simple_form.yes\", default: 'Yes'), true],\n          [I18n.t(:\"simple_form.no\", default: 'No'), false] ]\n      end\n\n      def input(wrapper_options = nil)\n        raise NotImplementedError,\n          \"input should be implemented by classes inheriting from CollectionInput\"\n      end\n\n      def input_options\n        options = super\n\n        options[:include_blank] = true unless skip_include_blank?\n        translate_option options, :prompt\n        translate_option options, :include_blank\n\n        options\n      end\n\n      private\n\n      def collection\n        @collection ||= begin\n          collection = options.delete(:collection) || self.class.boolean_collection","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/heartcombo/simple_form/blob/18f38aad0bdeca2ba1815043b94d96fdbbe6a325/lib/simple_form/inputs/collection_input.rb#L1-L36","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Prefer inheriting from a concrete class such as CollectionSelectInput and overriding only the parts you need","If the input is not actually collection-based, inherit from SimpleForm::Inputs::Base or StringInput instead"],"exampleFix":"# before\nclass StarInput < SimpleForm::Inputs::CollectionInput\n  # no #input defined -> NotImplementedError at render\nend\n\n# after\nclass StarInput < SimpleForm::Inputs::CollectionInput\n  def input(wrapper_options = nil)\n    @builder.collection_select(\n      attribute_name, collection, value_method, label_method,\n      input_options, input_html_options\n    )\n  end\nend","handlingStrategy":"validation","validationCode":"# fail fast at boot/test instead of mid-render\ndef implements_own_input?(klass)\n  klass.instance_method(:input).owner != SimpleForm::Inputs::CollectionInput\nend\n\nraise NotImplementedError, \"#{TagInput} must implement #input\" unless implements_own_input?(TagInput)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Render every registered custom input in a view spec so NotImplementedError fails in CI","Prefer subclassing concrete inputs (CollectionSelectInput) over the abstract CollectionInput","When implementing #input, accept wrapper_options to also avoid the arity deprecation"],"tags":["simple-form","collection-input","not-implemented","custom-input","abstract-method"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"18f38aad0bdeca2ba1815043b94d96fdbbe6a325","analyzedAt":"2026-08-21T18:23:08.988Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}