I've got user and they've got pets. All kinds of pets. Reptiles, fish, birds, and mammals. The Mammal model has two sub-classes, inherited through single table inheritance (STI): cats and dogs. My user has a method to get their last pet.
In a static pages controller, I have a method to visit the user's last pet:
def go_to_pet
redirect_to current_user.last_pet || root_path
end
Now the issue I'm running into is that when a cat or a dog is returned as the user's last pet, the app is looking for the cats or dogs controller, but I only have and need a mammals controller. The mammals controller is handling both cats and dogs pretty fine when it is actually invoked.
My question is such: how can I retrieve an instance of the Mammal class? I've tried Mammal.find(cat.id), but it will return a cat automatically because that's the whole point of STI.
The only ugly workaround I can think of is checking the class in the static pages controller (in the code block above) and then have redirect_to use the mammals controller, but I'd like to rather avoid this.
I tried to explicitly load the base class through Mammal.find(cat.id), but it returned an instance of the inherited class Cat based on the type column automatically. I had hoped to get an instance of the Mammal class.
I think you're trying to shoot yourself in the foot. If you have a Dog and Cat class instead of just a Mammal class then they probably deserve their own controllers. And if they behave the same then just make them trivial subclasses of a parent with shared behavior.
But if you really wanna do what you describe, I'd probably do it something like:
def go_to_pet
last_pet = current_user.last_pet
if last_pet.class.superclass.abstract_class?
redirect_to url_for(controller: last_pet.class.base_class.name.tableize, id; last_pet.id)
else
redirect_to current_user.last_pet || root_path
end
end
But mostly I'd probably just head it off in the routes.
resources :dogs, controller: 'mammals'