Kill the conditional in Ruby with polymorphism

I hate long conditionals, kinda like what I have in my phone PhonePlan class below:

class PhonePlan < Struct.new(:type)
def cost
if type == 'individual'
50
elsif type == 'family'
150
elsif type == 'business'
500
end
end
end

PhonePlan#cost is responsible for returning the cost based on the type, individuals cost is $50, family: $150 and business: $500 the specs can be seen here on Github, it shows us the expected behavior.

As my application grows, I know I am going to need to add other types to my cost method and my if statement is going to grow longer and longer. This is hard to read and extend.

I would like to create a class for each type (individual, family, business) and put the behavior that is specific to each type.

Individual type would like:

class Individual 
def self.return_cost
50
end
end

Family type would look like:

class Family 
def self.return_cost
150
end
end

And finally, business type would be:

class Business 
def self.return_cost
500
end
end

Now in my PhonePlan class I can get rid of the pesky conditional.

class PhonePlan < Struct.new(:type)
def cost
find_type.return_cost
end
private
def find_type
Object.const_get("#{type.capitalize}")
end
end

We’ve used const_get to find and initialize the specific class for the type. Then we just call return_cost, which is a class method and we can get the cost for that type.

I find that this solution is much cleaner and much easier to extend. Now We can add new types without ever changing PhonePlan. Which is a big win!

If you’ve enjoyed this post and want to dive a little deeper, feel free to clone the repo from GitHub. Also, here’s the main project that inspired this post.

Like what you read? Give Anonyo Hossain a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.