Simple medication dosage calculator

I am a nurse and I'm learning to code. I have coded this simple tool that helps me doing some common nursing formulas for medication. It works, however I think it is too bulky/redundant. Can you help me with some ideas for refactoring it?

class NursingFormulas
def initialize
puts "What do you want to do?"
puts "1) How many tablets should I administer?"
puts "2) How many ml should I administer?"
puts "3) What's the ml per hour rate of my IV?"
puts "4) What's the drop rate of my IV?"
puts "5) Exit"
choice = gets.chomp.to_i
case choice
when 1 then mass_for_mass
when 2 then mass_for_liquid
when 3 then iv_ml_rate
when 4 then iv_drop_rate
when 5 then exit(0)
else
exit(0)
end
end

def mass_for_mass
puts "What's the prescribed mass in mg?"
prescribed = gets.chomp.to_f
puts "What's the mass you've got in mg?"
mass = gets.chomp.to_f
result = prescribed / mass
puts "Administer #{result} tablets"
end

def mass_for_liquid
puts "What's the prescribed mass in mg?"
prescribed = gets.chomp.to_f
puts "What's the mass you've got in mg?"
mass = gets.chomp.to_f
puts "How many mL do you have?"
ml = gets.chomp.to_f
result = (prescribed / mass) * ml
puts "Administer #{result} ml"
end

def iv_ml_rate
puts "What's the volume in mL?"
volume = gets.chomp.to_f
puts "What's the time in hours?"
time = gets.chomp.to_f
result = (volume / time).round
puts "The rate is #{result} ml per hour"
end

def iv_drop_rate
puts "What's the volume in mL?"
volume = gets.chomp.to_f
puts "What's the time in hours?"
time = gets.chomp.to_f
time = time * 60
puts "What's the drop factor?"
factor = gets.chomp.to_f
result = ((volume / time) * factor).round
puts "The drop rate is #{result} drops per minute"
end
end

• You don't need classes. Jan 29 '16 at 11:24

2 Answers

Here is a solution using the Command Pattern.

Each action will live in its own class. I'm using some mixins so we don't have repeated code.

nursing_formulas.rb

require_relative "formulas/mass_for_mass"
require_relative "formulas/mass_for_liquid"
require_relative "formulas/iv_ml_rate"
require_relative "formulas/iv_drop_rate"

class NursingFormulas
def initialize
show_instructions

@instructions = {
1 => MassForMass.new,
2 => MassForLiquid.new,
3 => IvMlRate.new,
4 => IvDropRate.new
}

choice = gets.chomp.to_i

@instructions.key?(choice) ? @instructions[choice].do : exit(0)
end

def show_instructions
puts "What do you want to do?"
puts "1) How many tablets should I administer?"
puts "2) How many ml should I administer?"
puts "3) What's the ml per hour rate of my IV?"
puts "4) What's the drop rate of my IV?"
puts "5) Exit"
end
end


mass_for_mass.rb

require_relative "mixins/mass_actions"

class MassForMass
include MassActions

def do
result = ask_for_prescribed_mass / ask_for_mass
puts "Administer #{result} tablets"
end
end


mass_for_liquid.rb

require_relative "mixins/mass_actions"

class MassForLiquid
include MassActions

def do
prescribed = ask_for_prescribed_mass
mass = ask_for_mass
ml = ask_for_ml

result = (prescribed / mass) * ml
puts "Administer #{result} ml"
end

def ask_for_ml
puts "How many mL do you have?"
gets.chomp.to_f
end
end


iv_ml_rate.rb

require_relative "mixins/iv_actions"

class IvMlRate
include IvActions

def do
volume = ask_for_volume
time = ask_for_time

result = (volume / time).round
puts "The rate is #{result} ml per hour"
end
end


iv_drop_rate.rb

require_relative "mixins/iv_actions"

class IvDropRate
include IvActions

def do
volume = ask_for_volume
time_in_min = ask_for_time * 60
factor = ask_for_drop_factor

result = ((volume / time_in_min) * factor).round
puts "The drop rate is #{result} drops per minute"
end

def ask_for_drop_factor
puts "What's the drop factor?"
gets.chomp.to_f
end
end


MIXINS

mass_actions.rb

module MassActions
def ask_for_prescribed_mass
puts "What's the prescribed mass in mg?"
gets.chomp.to_f
end

def ask_for_mass
puts "What's the mass you've got in mg?"
gets.chomp.to_f
end
end


iv_actions.rb

module IvActions
def ask_for_volume
puts "What's the volume in mL?"
gets.chomp.to_f
end

def ask_for_time
puts "What's the time in hours?"
gets.chomp.to_f
end
end

• Hope this helps you to write more formulas in the future :) Jan 30 '16 at 15:29
• This is pretty great <3. I'll spend some time understanding the code I like this way of doing it. Thanks a lot! Jan 30 '16 at 16:44
• You're welcome! Let me know if you don't understand something Jan 30 '16 at 16:48

I agree with @Nakilon for a float

All your methods are static (they do not read into the state of the class) so you do not need a class.

What you do need is a way of asking for a float that you do so many times.

Extracting asking for a float into a function will also help you add error-checking easily.

• I know, i was planning to make more tools in the application other than the dosage calculator that's why I made it a class to separate it from the other tools but I guess it could also just be a module or something. But yes, Mario's answer is pretty much what I was looking for. :) Jan 30 '16 at 19:18