Modeling Dynamic Product Fields in Rails with the EAV Pattern
April 22, 2025
In some applications, products aren’t all the same. A bottle of milk, a car, and a cow each need their own unique fields. Traditional relational databases don’t play well with highly dynamic schemas — and that’s where the Entity-Attribute-Value (EAV) pattern comes into play.
If you’re working with Rails and want to allow flexible product definitions without constantly updating migrations, the EAV pattern is a solid solution.
Let’s connect!
If you’re building flexible systems in Rails, working with dynamic data models, or just want to geek out over architecture patterns — I’d love to hear from you.
What is the EAV Pattern?
Entity-Attribute-Value structures your data in a way that supports dynamic attributes. Instead of adding new columns for every product field, you store:
- Entity → the item (e.g., Product)
- Attribute → the field name (e.g., color, engine_size)
- Value → the actual value for that field (e.g., red, 2.0L)
This allows you to build systems where users can define their own product fields without altering your database schema.
EAV in Rails — A Practical Setup
Let’s say we’re building a marketplace where users can list anything from milk to motorcycles.
Models:
class Product < ApplicationRecord
belongs_to :product_type
has_many :product_values
end
class ProductType < ApplicationRecord
has_many :product_attributes
end
class ProductAttribute < ApplicationRecord
belongs_to :product_type
# name:string, data_type:string
end
class ProductValue < ApplicationRecord
belongs_to :product
belongs_to :product_attribute
# value:string (or use jsonb if you want typed values)
end
Example Usage
Imagine you define a new ProductType called “Milk” and give it these attributes:
- brand (string)
- fat_content (decimal)
- expiration_date (date)
You then create a Product of type “Milk” and associate it with specific values for each attribute.
Now you can add a Car, define engine_size, door_count, and fuel_type — and your schema doesn’t need to change at all.
Pros and Cons
Pros
- Super flexible.
- Ideal for user-driven field definitions.
- Works well for CMSs, marketplaces, or low-code platforms.
Cons
- Slightly more complex querying.
- Type validation and casting need extra care.
- You’ll likely need a UI to handle dynamic form rendering.
Extra Tips
- Use a jsonb column in product_values to support complex data types.
- Add methods like product.attribute(“fat_content”) for better developer experience.
- Consider indexing product_attribute_id + value for performance if you’ll filter by dynamic fields.
Wrapping Up
Rails gives us powerful tools, and combining them with patterns like EAV lets us step outside the strict schema mold when we need to.
If you’re building something flexible, user-customizable, or schema-less at runtime — the EAV pattern is your friend.
Let me know if you’re tackling something like this or if you’ve found a hybrid approach that works better for your use case!
Top comments (0)