Minimal Captcha (Ruby)

Sun 19 Sep 2021
Reading time: (~ mins)

Anywhere there is an open contact form on the internet you can bet that there will be automated bots spamming it constantly. Instead of adding more dependencies to you project or diving into some configuration hell why not spend two minutes to code up a first-principle solution.

Spammers use low effort attempts so we don't have to put much effort curb their activity. Here's a straight forward ruby module you can add to any project:

module EmailHelpers
  def plus_minus
    rand > 0.5 ? '-' : '+'
  end

  def gen_num(num)
    rand(1..num)
  end

  def generate_captcha(max = 10)
    captcha = "#{gen_num(max)}"\
              "#{plus_minus}"\
              "#{gen_num(max)}"\
              "#{plus_minus}"\
              "#{gen_num(max)}"
    @question = captcha.to_s
    @answer   = eval(captcha)
  end
end

We randomly generate 3 numbers and addition/subtraction operators between them as a challenge(ie. 3 + 7 - 4) for any form submitter. Keeping the numbers small should make the problem no issue for anyone trying to submit your form under the assumption that they can read and do basic maths.

Then in your preexisting form add a hidden input tag which the user must successfully match:

%label Verify you are human :)
%div
  = @question
  \=
%input{ type: 'hidden', value: @answer, name: 'q' }
%input{ id: 'Human', name: 'human', type: 'number' }

Finally in your POST handler check that the :human param matches the :q param:

post '/email' do
  process_email if params[:q] == params[:human]
end

No javascript, no page bloat and will not annoy your users by making them play Simon Says with Google's pattern matching algorithms.

You can see it in action if you use my contact form linked below. Enjoy :)


Questions? Free free to contact me anytime :)

Get Notified of Future Posts