Reputation: 32070
So I have an odd set of circumstances, which basically requires a static implementation attached to an Active Record object. Here is the background.
I have a Product
, which is sold by one or more Provider
(has_many_through :product_providers
). However, each Provider
has a specific set of rates for each Product
based on a request form, consisting of unique rates (dollar amounts) and algorithms. Due to the complexity of the algorithms, they are stored in separate Ruby classes.
What I'm trying to accomplish is how to associate a ProductProvider
with a static class. My first implementation was something along the lines of:
# slug = 'acme-widget'
slug.split('-').join('/').camelize.constantize
This would give me the class, Acme::Widget
. This technically works, but I feel like there must be a better pattern.
Upvotes: 1
Views: 228
Reputation: 4420
I've previously solved this (overall) problem using the classy_enum gem: it takes care of getting from the database-stored value to the right class instance, and brings some other enum conveniences along for the ride.
However, it's been some time since I last used it, and the gem is now no longer actively maintained. While it would still be a good fit for your problem, it might need some updates to work with Rails 5.0+.
If you're going to implement it yourself, be careful when calling constantize
on possibly-user-affected input. A static hash would be safest; a scoped const_get
ProviderStrategy.const_get(s)
, or a constantize
on a restricted string ("Provider::#{s}".constantize
), is next best.
This is important because if a [malicious] user is able to choose an arbitrary constant in the running system, it will generally just error when it fails to respond to a required method, but there are always tricky edge cases.
Upvotes: 1