Home Let's build an API in Rails - Part 01
Post
Cancel

Let's build an API in Rails - Part 01

In today’s post I will teach you how to build an API in Rails from scratch with several features and implementing some development patterns that allow our API to expand without much code and that it becomes very easy to implement new features.

Requirements

First we need an operating system in this case we gonna use Debian 10, this installation tutorial is considering only the use of the terminal and the minimal system without a graphical interface, which can be used in a virtual machine or directly in the operating system installed in hardware, in addition, we need ruby and Rails ​​already installed on the machine, in this post we will use ruby ​​3.2.2 and Rails 7.0.7.

Steps

  1. Defining the API scope
  2. Class diagram
  3. Rails commands
  4. Rails code
  5. Seeds and Rails console
  6. Conclusion

Defining the API scope

Our API is going to be very simple, basically we are going to make an API that receives information from users about their loans and we are going to calculate the interest rates of these loans, from that we are going to build a dashboard with some global information according to what was informed by the users.

Class diagram

classDiagram
class Bank {
    integer bank_id
    string bank_name
    integer bank_fed_id
    string bank_location
}

class Loans {
    date loan_date
    bool credit_needed
    integer bank_id
    integer user_id
    decimal amount
    bool early_payoff_penalty
    integer term
    decimal origination_fee
    decimal late_fee
    integer fico_score_at_date
}

class User {
    integer user_id
    string email
}

Bank <|-- Loans
User <|-- Loans

So, once we have defined how our classes are going to be we can start building our API in Rails, basically we have a Bank class that can have N Loans and a User class that can have N Loans also in rails we call this has_many relation :through that in this case the Loans class is born from an N to N relationship between Banks and Users with their due unique attributes of this relationship, not just a direct relationship of identity between the classes

Rails commads

Today we are basically going to use two rails commands to create our models and make them persist in the database.

This command creates a model that is an object representation of relational data.

1
rails g model model_name attributes

This command sends the migrations that were created with the previous command

1
rails db:migrate

Rails code

Let’s create our models, let’s create the Bank model first, we will need to run the following command:

1
rails g model Bank bank_name bank_fed_id:integer bank_location

Now we can run the migration:

1
rails migrate

After that we can create the User model with the following command:

1
rails g model User email

And again we can run the migration:

1
rails migrate

And now we can create the N to N relationship class between Banks and Users:

1
rails g model Loan loan_date:date credit_needed:boolean bank:references user:references amount:decimal early_payoff_penalty:boolean term:integer origination_fee:decimal late_fee:decimal fico_score_at_date:integer

Finally, we can run the migration to create the last table:

1
rails migrate

After that, we already have our tables created and ready to receive data, but first we need to inform the relationships and how they communicate in the model’s class files.

In the Bank model, we need to change the file so that it looks like this:

1
2
3
4
class Bank < ApplicationRecord
  has_many :loans
  has_many :users, through: :loans
end

In the User model, we need to change the file so that it looks like this:

1
2
3
4
class User < ApplicationRecord
  has_many :loans
  has_many :banks, through: :loans
end

Finally in the Loan model we have to have a code like this:

1
2
3
4
class Loan < ApplicationRecord
  belongs_to :bank
  belongs_to :user
end

After that we have our ORM (object relational mapping) complete. If you want to know more about this you can see more information here: https://www.freecodecamp.org/news/what-is-an-orm-the-meaning-of-object-relational-mapping-database-tools/

Seeds and Rails console

Now we can create data to test ourselves if our models are working correctly. For that we are going to use rails Seeds.rb file that can be found in db/seeds.rb to throw test data to our database.

We are going to create 5 Banks and 20 Users to test our relationships, each User will have between 1 and 5 Loans, Banks can have more than one Loan.

Our seeds file will look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
5.times do |i|
  Bank.create!(bank_name: 'bank ' + i.to_s, bank_fed_id: rand(0..16), bank_location: 'bank location ' + i.to_s)
end

20.times do |i|
  User.create!(email: 'email ' + i.to_s)
end

User.all.map do |user|
  rand(1..5).times do
    user.loans.create!(loan_date: Date.today-rand(1000), 
                        credit_needed:[true, false].sample,
                        bank: Bank.all.sample,
                        amount: rand(100.0..100000.0),
                        early_payoff_penalty: [true, false].sample,
                        term: rand(6..360),
                        origination_fee: rand(0.001..0.01),
                        late_fee: rand(0.001..0.02),
                        fico_score_at_date: rand(300..850))
  end
end

Now we can run the command to insert this dummy data into our database so we can check if our relationships are correct:

1
rails db:seed

If it does not return any error, the console will just show a new line to insert a new command.

After that we can check in the Rails console if the information is persisted:

1
rails c

And then we can use User.all to check if user data is recorded, just like Bank.all and Loan.all.

1
User.all

You will see a result similar to this:

1
2
3
4
5
6
User Load (0.5ms)  SELECT "users".* FROM "users"
 =>                                                         
[#<User:0x00007f07dd573618 id: 161, email: "email 0", created_at: Sat, 19 Aug 2023 02:40:32.393240000 UTC +00:00, updated_at: Sat, 19 Aug 2023 02:40:32.393240000 UTC +00:00>,
 #<User:0x00007f07dd5f1ae0 id: 162, email: "email 1", created_at: Sat, 19 Aug 2023 02:40:32.398077000 UTC +00:00, updated_at: Sat, 19 Aug 2023 02:40:32.398077000 UTC +00:00>,
 #<User:0x00007f07dd5f1a40 id: 163, email: "email 2", created_at: Sat, 19 Aug 2023 02:40:32.402377000 UTC +00:00, updated_at: Sat, 19 Aug 2023 02:40:32.402377000 UTC +00:00>,
 #<User:0x00007f07dd5f19a0 id: 164, email: "email 3", created_at: Sat, 19 Aug 2023 02:40:32.406591000 UTC +00:00, updated_at: Sat, 19 Aug 2023 02:40:32.406591000 UTC +00:00>]

And using the other commands you will get similar results.

You can also test the relationships using the following commands:

1
User.first.loans
1
User.first.banks
1
Bank.first.loans
1
Bank.first.users

Conclusion

With this first post I made an introduction of what our API will be like at least at the Model level, with this we can advance in the functionalities based on our data, in the next posts we will learn about model validations, model tests and other subjects more related to this.

I hope you like it, if you want and can you can share this text, I will be posting new content daily, favorite this blog to have access to new knowledge. Thanks to everyone who read this post.

This post is licensed under CC BY 4.0 by the author.