I Wrote Some Terrible Code

Last week I pushed up the Math API I had been thinking of for a while but only worked on briefly. The code was quite concise but rather disconnected. The question generator had no knowledge of the solution checker for example. Original code below.

def additionGenerator(opts = {})  
  total = rand(opts[:max].to_i)
  num1 = rand(total)
  num2 = total - num1
  { :num1 => num1, :num2 => num2 }.to_json
end

def additionChecker(opts = {})  
  if params[:num1].to_i + params[:num2].to_i == params[:answer].to_i
    returnCorrect
  else
    returnIncorrect
  end
end

post '/addition.json' do  
  additionGenerator(params)
end

post '/additionchecker.json' do  
  additionChecker(params)
end  

To fix this I created a class for an addition question that generated the question and contained internal logic for checking for the solution.

class Addition  
  attr_accessor :num1, :num2, :answer

  def initialize(opts = {})
    total = set_total(opts[:max])
    self.num1 = opts[:num1] || rand(total)
    self.num2 = opts[:num2] || total - self.num1
    self.answer = opts[:answer]
  end

  def correct?
    self.num1.to_i + self.num2.to_i == self.answer.to_i
  end

  def set_total(value = 10)
    rand(value.to_i - 1) + 1
  end

  def to_h
    { num1: self.num1, num2: self.num2, answer: self.answer }
  end

  def to_json
    self.to_h.to_json
  end
end

post '/addition.json' do  
  Addition.new(params).to_json
end

post '/additionchecker.json' do  
  {correct: Addition.new(params).correct?}.to_json
end  

This increases the lines of code but feels much more connected. Because there is no backend I do have to recreate the object when checking if the submitted solution is correct which feels a little unnatural at first. Being able to call .correct? on all of the question objects seems like a nice way of checking solutions compared to passing some params to a isolated function.

It seems like overkill at the moment but will hopefully lead to better design choices in the future as the app grows and should make it easier to build a ruby library/gem from the code.