{"record":{"id":"4e5b0183bcffe406","repo":"ViewComponent/view_component","slug":"a-method-called-setter-method-name-already-exist","errorCode":null,"errorMessage":"A method called 'SETTER_METHOD_NAME' already exists and would be overwritten by the 'SETTER_NAME' polymorphic slot setter.\n\nPlease choose a different setter name.","messagePattern":"A method called 'SETTER_METHOD_NAME' already exists and would be overwritten by the 'SETTER_NAME' polymorphic slot setter\\.\n\nPlease choose a different setter name\\.","errorType":"exception","errorClass":"ViewComponent::AlreadyDefinedPolymorphicSlotSetterError","httpStatus":null,"severity":"error","filePath":"lib/view_component/slotable.rb","lineNumber":263,"sourceCode":"            poly_callable = poly_attributes_or_callable\n            poly_slot_name = nil\n          end\n\n          poly_slot_name ||=\n            if collection\n              \"#{ActiveSupport::Inflector.singularize(slot_name)}_#{poly_type}\"\n            else\n              \"#{slot_name}_#{poly_type}\"\n            end\n\n          memo[poly_type] = __vc_define_slot(\n            poly_slot_name, collection: collection, callable: poly_callable\n          )\n\n          setter_method_name = :\"with_#{poly_slot_name}\"\n\n          if method_defined?(setter_method_name)\n            raise AlreadyDefinedPolymorphicSlotSetterError.new(setter_method_name, poly_slot_name)\n          end\n\n          define_method(setter_method_name) do |*args, **kwargs, &block|\n            __vc_set_polymorphic_slot(slot_name, poly_type, *args, **kwargs, &block)\n          end\n\n          define_method :\"with_#{poly_slot_name}_content\" do |content|\n            send(setter_method_name) { content.to_s }\n\n            self\n          end\n        end\n\n        registered_slots[slot_name] = {\n          collection: collection,\n          renderable_hash: renderable_hash\n        }\n      end","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/ViewComponent/view_component/blob/9f22c36fa7d7b44098a8ed97472e3b4674ae420f/lib/view_component/slotable.rb#L245-L281","documentation":"ViewComponent raises this error while registering a polymorphic slot. When renders_one or renders_many receives a types: hash, __vc_register_polymorphic_slot derives a setter method named with_<poly_slot_name> for each type (default <slot>_<type> for singular slots, <singularized_slot>_<type> for collections, overridable with as:). Before calling define_method it checks method_defined?(setter_method_name) at lib/view_component/slotable.rb:262 and raises instead of silently overwriting an existing method.","triggerScenarios":"Declaring a polymorphic slot whose derived setter already exists. Examples: renders_one :row_header defines with_row_header, then renders_many :rows, types: { header: { renders: RowHeaderComponent, as: :row_header } } derives with_row_header again; two entries in one types hash deriving the same name; a hand-written def with_item_extra method; or an ancestor class already defining the setter, since method_defined? includes inherited methods.","commonSituations":"Adding a polymorphic slot to a component that already has regular slots with overlapping names; refactoring a plain renders_one slot into a polymorphic renders_many without renaming; choosing short as: aliases such as :header that collide with existing with_header setters; deep inheritance where a parent class defines the colliding method.","solutions":["Rename the colliding polymorphic type with as: so its setter becomes unique (for example as: :heading)","Rename or remove the other slot or instance method that already owns the with_<name> setter","Check ancestors with SomeComponent.method_defined?(:with_row_header) to locate which class defines the colliding method","Keep polymorphic type keys and as: aliases unique per component"],"exampleFix":"# before\nclass TableComponent < ViewComponent::Base\n  renders_one :row_header, RowHeaderComponent # defines with_row_header\n\n  renders_many :rows, types: {\n    header: { renders: RowHeaderComponent, as: :row_header } # collides with with_row_header\n  }\nend\n\n# after\nclass TableComponent < ViewComponent::Base\n  renders_one :row_header, RowHeaderComponent\n\n  renders_many :rows, types: {\n    header: { renders: RowHeaderComponent, as: :row_heading }\n  }\nend","handlingStrategy":"validation","validationCode":"# mirror the framework check before declaring a polymorphic slot\ndef polymorphic_setters_free?(klass, slot_name, types, collection:)\n  types.all? do |type, opts|\n    base = collection ? slot_name.to_s.singularize : slot_name.to_s\n    name = (opts.is_a?(Hash) ? opts[:as] : nil) || \"#{base}_#{type}\"\n    !klass.method_defined?(\"with_#{name}\")\n  end\nend\n\npolymorphic_setters_free?(MyComponent, :rows, { header: { renders: RowHeaderComponent } }, collection: true) # => true when free","typeGuard":null,"tryCatchPattern":"# only for config-driven registration; static declarations should fail at boot\nbegin\n  renders_many :rows, types: configured_types\nrescue ViewComponent::AlreadyDefinedPolymorphicSlotSetterError\n  configured_types = sanitize_type_aliases(configured_types)\n  retry\nend","preventionTips":["Compute every derived setter name (with_ plus base underscore type) before declaring a polymorphic slot","Give polymorphic types distinctive as: names instead of generic ones like header or item","Before adding slots in a subclass, list inherited names with SomeParent.registered_slots.keys","Keep polymorphic types in one place so entries cannot drift into collisions across edits"],"tags":["ruby","rails","view-component","slots","polymorphic-slots","method-collision"],"backgroundTag":"method-name-collision","analyzedSha":"9f22c36fa7d7b44098a8ed97472e3b4674ae420f","analyzedAt":"2026-08-23T10:20:47.008Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}