---
title: "Changing a polymorphic_type in Rails"
description: "Rails normally persists a polymorphic association’s type as the parent class name, so moving Car under Garage changes stored values from “Car” to “Garage::Car” and can break lookups for older Key records. The post presents an alternative for the Vehicle/Key example: override polymorphic_name so Garage::Car and Garage::Boat resolve to stable arbitrary strings such as “car” and “boat,” reducing coupling between namespaces and database data. During transition, the association scope must explicitly accept both legacy class-name values and new arbitrary values, because Rails uses only the single value returned by polymorphic_name when querying; existing rows can then be cleaned up with a migration, script, or MaintenanceTasks. After cleanup, the temporary unscope can be removed, while class and module renames require updating the mappings rather than database records. The approach adds complexity and is presented as worthwhile only when near-term naming changes are likely."
---

# Changing a polymorphic\_type in Rails

[Shopify](https://yomu.fyi/company/shopify) · 2023-10-18 · Feb 18, 2022

**Type:** Explainer

## Summary

Rails normally persists a polymorphic association’s type as the parent class name, so moving Car under Garage changes stored values from “Car” to “Garage::Car” and can break lookups for older Key records. The post presents an alternative for the Vehicle/Key example: override polymorphic\_name so Garage::Car and Garage::Boat resolve to stable arbitrary strings such as “car” and “boat,” reducing coupling between namespaces and database data. During transition, the association scope must explicitly accept both legacy class-name values and new arbitrary values, because Rails uses only the single value returned by polymorphic\_name when querying; existing rows can then be cleaned up with a migration, script, or MaintenanceTasks. After cleanup, the temporary unscope can be removed, while class and module renames require updating the mappings rather than database records. The approach adds complexity and is presented as worthwhile only when near-term naming changes are likely.

## Context

Moving model classes into a different module changes their namespaces, causing Rails to store new polymorphic type values alongside old class-name values. The association then cannot find all related records unless it knows about every possible value, and existing records would otherwise require updates when classes or namespaces change.

## Approach / What changed

Override polymorphic\_name to store stable arbitrary strings instead of class names, redefine the association scope to read both legacy and new type values during the transition, and clean up existing records with a migration, script, or MaintenanceTasks. Once cleanup is complete, remove the temporary unscope and maintain the class-to-string mappings.

## Takeaways

- Rails polymorphic associations use the value returned by polymorphic\_name for the stored type and association lookup.
- A transition scope can match both legacy class names such as “Car” and new arbitrary values such as “car” before database cleanup.
- The method reduces coupling between code namespaces and database records, but adds complexity that may not suit most use cases.

**Tags:** [Architecture](https://yomu.fyi/topic/architecture), [Refactoring](https://yomu.fyi/topic/refactoring)

- Source: [Shopify](https://shopify.engineering/changing-polymorphic-type-rails)
- Source URL: https://shopify.engineering/changing-polymorphic-type-rails
- Ingested by Yomu: 2026-08-30T15:27:41.844Z

[Read original post](https://shopify.engineering/changing-polymorphic-type-rails)
