I've heard Sinatra many times in the ruby-rails ecosystem, but only got introduced to it in The Odin Project(TOP). Sinatra is a lightweight ruby web framework from which you can build web apps with minimal efforts. TOP encourages to learn Sinatra before rails to understand many things that rails do under the hood.

Today we'll build a Sinatra app, which takes input(in an HTML form) and tells the user whether the number is a Prime number or not.

Note: I expect you to know the basics of Ruby Programming language to get along with this project.

Initial Steps

First, you'll need Ruby. You can install it from GoRails guide from here. You don't need Rails, so you can skip installing rails.

Then, install Sinatra and its tools which make our development easier.

gem install sinatra
gem install sinatra-contrib

Next, create a new project directory(in our case "sinatra-project"), cd into it and create a file app.rb where our sinatra code runs:

mkdir sinatra-project
cd sinatra-project
touch app.rb

Let's Code

A simple Hello World app:

# app.rb

require 'sinatra'

if development?
  require 'sinatra/reloader'
end

get '/' do
  "Hello World"
end

The first line include sinatra framework and sinatra/reloader is a tool that we can use so that whenever we make change to the app.rb we don't need to restart the server manually. Also, it's not a good practice to include sinatra/reloader, so we'll only use it in development environment. development? is a built-in method in Sinatra.

Then we say, GET method in /(root dir), should respond with a "Hello World" message. This is just a text we send and not some HTML.

Now run, ruby app.rb from your terminal. If you want to specify custom port and IP run ruby app.rb -o 0.0.0.0 -p 5000
This will run a server and you can see your website.

Now let's render a HTML page. We'll use ruby default templating engine ERB. create a new folder views and a views/index.erb file:

mkdir views
touch views/index.erb

Add a simple HTML code in it:

<!-- views/index.erb -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Prime Number Checker</title>
    <style>
      .result{
        color: green;
      }
    </style>
  </head>
  <body>
    <div>
      <h2>Prime Number Checker</h2>
      <p>Insert a number below and I'll tell you whether it's a Prime number or not!</p>
    </div>
    
    <div>
      <form>
        <label for="primecheck">Number: </label>
        <input type="text" name="primecheck"/>
        <input type="submit" value="Check Now"/>
      </form>
    </div>
    
    <div>
      <p class="result"></p>
    </div>
  </body>
</html>

The Logic

We'll implement the logic in app.rb and then pass the final result as a variable to the index.erb file.

person holding 3x3 Rubik's Cube
Photo by NeONBRAND / Unsplash

First the logic, we'll make use of built-in prime library and we can check whether a number is prime or not with .prime?(number) method. We'll create a private method for this implementation. See below:

require 'sinatra'
require 'prime'

if development?
  require 'sinatra/reloader'
end

get '/' do
  erb :index
end

private
  def is_prime?(number)
    return Prime.prime?(number) # this will return a boolean, true or false
  end

Whenever the user submits the form by inserting a number in the text field, It will be sent as a params to the URL. Go and insert a number in the form and click on "Check Now" button, you'll see the URL change to /?primecheck=5. Now in app.rb, you can catch this params and then work on it. For example, params["primecheck"] will be "5" in this case.

Now update the code in app.rb:

require 'sinatra'
require 'prime'

if development?
  require 'sinatra/reloader'
end

final_answer = ""

get '/' do
  user_input = params["primecheck"] || ""
  
  if user_input.to_i != 0
    final_answer = is_prime?(user_input.to_i) ? "YES, #{user_input.to_i} is a prime number!" : "NO, #{user_input.to_i} is not a prime number!"
  elsif user_input == ""
    final_answer = ""
  else
    final_answer = "Please enter a proper number!"
  end
  
  erb :index, locals: { final_answer: final_answer }
end

private
  def is_prime?(number)
    return Prime.prime?(number) # this will return a boolean, true or false
  end

The above added code is self-explanatory. We'll capture the params in user_input variable and then store the result in our final_answer variable. Then we'll pass the final_answer variable to the index.erb using locals: { final_answer: final_answer }.

You also need to change index.erb, the <p class="results"></p> as below:

<p class="result"><%= final_answer %></p>

You can also see that we've added more validations in elsif and else statement, if the user doesn't enter proper number(say "abc"), then this will display "Please enter a proper number!"

Conclusion

Hope you got a good basic understanding of what Sinatra is and how it works. We built a Prime Checker app along the way. You can also add features like Factorial of a number or Guess a number game to make yourself more comfortable with Sinatra.

If you want to learn more see Official docs, it has all the content that you'll ever need to know. Also, see some cool Sinatra projects here.

Now, Let there be the End 🙏! Bye, See you soon!