The CRUD on the Backend of Active Record/Sinatra
Tags: webdev, beginners, tutorial, ruby
Published: 2023-02-13 00:15:53

I told you that CRUD will return in Active Record (refer to my other blog about The SQL to CRUD: The Use of Structured Query Language to Create, Read, Update, and Destroy).  The time is now and CRUD is back.  Today I will talk about CRUD in the context of Active Record and Sinatra.

Again, a table of muscles will be used, since it lends itself well to creating a database.  Let us follow CRUD in Active Record to the letter.

First we will create a table by creating a migration.  Migrations are created in order to create or modify a table.  I will not go into too much detail about migrations because that is another topic of discussion.

```
rake db:create_migration NAME=create_muscles
```
Once we create our migration a file is created which is appropriately named and timestamped (`20230203201213_create_muscles.rb`).  The following code is added.

```
class CreateMuscles < ActiveRecord::Migration[6.1]
  def change
    create_table :muscles do |t|
      t.string :name
      t.string :origin
      t.string :insertion 
      t.string :action 
      t.string :innervation 
      t.string :blood_supply
      t.string :url
      t.integer :bodypart_id
    end
  end
end
```
Note that this class Create Muscles inherits methods from `ActiveRecord::Migration`.  It creates a table with the columns name, origin, insertion, action, innervation, blood_supply, url, and bodypart_id.  All these are strings except bodypart_id which is an integer which refers to the primary key in another table  called body_parts which is created in the same aforementioned way.  

```
class CreateBodyparts < ActiveRecord::Migration[6.1]
  def change
    create_table :bodyparts do |t|
      t.string :name 
    end
  end
end
```
`body_parts` has a one to many relationship with `muscles`.  See the ERD (entity relationship diagram) below.


![one to many relationship](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8g1ef60lz6fh2812m6jo.png)


Speaking of that, let us finish the migration with this command.

```
rake db:migrate
```
Now our schema is created which looks like this.

```
ActiveRecord::Schema.define(version: 2023_02_03_202632) do

  create_table "bodyparts", force: :cascade do |t|
    t.string "name"
  end

  create_table "muscles", force: :cascade do |t|
    t.string "name"
    t.string "origin"
    t.string "insertion"
    t.string "action"
    t.string "innervation"
    t.string "blood_supply"
    t.string "url"
    t.integer "bodypart_id"
  end

end
```
Now we create the models.  The models are classes which inherit methods from `ActiveRecord::Base`.  These classes correspond to  tables. Instances which correspond to rows can and will be created from these classes. Look at the models below for Bodypart and Muscle.  These are in separate files but I display them in one code block for the reader.  Since each model inherits methods there is very little code to write but the relationships are clearly defined to allow the tables to relate to each other.  It is like real life.  Body parts have many muscles and a muscle typically belongs to one body part.

```
class Bodypart < ActiveRecord::Base
    has_many :muscles
end

class Muscle < ActiveRecord::Base
    belongs_to :bodypart
end
```
Now that our database is set up, I can finally talk about CRUD methods used to manipulate databases.

**Create:**  

Now that we have our models established we can talk about the "C" in CRUD, create.

The `new` method creates a new instance while the `save` method saves an instance to the database.  It is important to be aware that it is not enough to create a new instance but that instance has to be saved (persisted) to the data base.  Lets take a generic model called User which has attributes name and job.

```
User.new(name: "Goku", job: "Saiyan with a level of over 9000")
User.name = "Goku"
User.job = "Saiyan with a level of over 9000"
```
This creates an instance of Goku but does not persist him to the database. It means that the data exists but has not been added to the table.  It's like a ball player with no team.

```
User.save
```
This adds Goku to the database.

![Goku](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k48cm3t2i1n40t136lho.gif)

Now, this is all well and good, but there is an easier way to do this.  The `create` method can be used.  It combines the `new` and `save` methods into one.  I demonstrate this using the create method to create an instance of muscle and persist it to the muscles database as demonstrated below.

```
Muscle.create(
 name: "deltoid",
 origin: "lateral one-third of the clavicle, acromion, the lower lip of the crest of the spine of the scapula",
 insertion: "deltoid tuberosity of the humerus",
 action: "abducts arm; anterior fibers flex & medially rotate the arm; posterior fibers extend & laterally rotate the arm",
 innervation: "axillary nerve (C5,6)",
 blood_supply: "posterior circumflex humeral a.",
 url:
  "https://cdn-aolkg.nitrocdn.com/JEsNUzsMoDdLqhSXkopLhNFWnBniacqf/assets/images/optimized/rev-5038be8/wp-content/uploads/2014/02/deltoids-muscle-attachments.jpg",
 bodypart_id: 264
)
=> #<Muscle:0x0000564b01685f40
 id: 415,
 name: "deltoid",
 origin: "lateral one-third of the clavicle, acromion, the lower lip of the crest of the spine of the scapula",
 insertion: "deltoid tuberosity of the humerus",
 action: "abducts arm; anterior fibers flex & medially rotate the arm; posterior fibers extend & laterally rotate the arm",
 innervation: "axillary nerve (C5,6)",
 blood_supply: "posterior circumflex humeral a.",
 url:
  "https://cdn-aolkg.nitrocdn.com/JEsNUzsMoDdLqhSXkopLhNFWnBniacqf/assets/images/optimized/rev-5038be8/wp-content/uploads/2014/02/deltoids-muscle-attachments.jpg",
 bodypart_id: 264>
```
We have just created a muscle and added it to the database.  Note that an id is automatically generated, it is autoincrementing.

**Read:**

Now that we can create rows of data in a table it is imperative that we can access this data.  This is the "R" is CRUD which is read.  There are many methods here but I will highlight the commonly used ones.  Let us use the Muscle model.  Think of the database as an array of instances (technically the data from the instances) stored in a table.

- `Muscle.all` returns a collection with all muscles.
- `Muscle.first` returns the first muscle.
- `Muscle.find(3)` returns the muscle with an id number of 3.
- `Muscle.find_by(name: "deltoid")` finds a muscle with the name of deltoid.  This can be used for any attribute within that class.
- `Muscle.where(bodypart_id: 5, action: "flex the knee").order(name: :desc)` finds all muscles located in a body part with the identifier of 5 which flex the knee in descending order by name.

**Update:**

We can read and find data in a table now.  Let us talk about the "U" in CRUD, update.  We can update a single record by attribute(s) using the `update` method.

```
deltoid = Muscle.find_by(name: "deltoid")
deltoid.update(bodypart_id: 250)
```
We can also update several records at the same time using the `update_all` method.

```
User.update_all(job: "Super Saiyans with level > 9000")
```
**Delete:**

The "D" is CRUD is delete/destroy.  The methods are straightforward.  For a single record we can use the `destroy` method. For multiple records we can use the `destroy_by` or `destroy_all` method.

```
biceps = Muscle.find_by(name: "biceps brachii")
biceps.destroy

Muscle.destroy_by(name: "biceps brachii") //deletes all muscles named "biceps brachii"

Muscle.destroy_all //deletes all muscles
```
Now we can perform CRUD methods on our records in the database.  With the addition of Sinatra we can create a backend with our records which can be accessed from the front end.  We can use CRUD methods to do this.  Here is a quick overview.  Note that below we are using and HTTP method combined with a relative path to make changes to the backend server.  _The combination of an HTTP method and a relative path is called a route._

**Create:** the use of `post`

```
    post '/muscles' do
      new_muscle = Muscle.create(
        name: params[:name], 
        origin: params[:origin], 
        insertion: params[:insertion], 
        action: params[:action], 
        innervation: params[:innervation], 
        blood_supply: params[:blood_supply], 
        url: params[:url],
        bodypart_id: params[:bodypart_id].to_i
        )
      new_muscle.to_json
    end
```
This `post` method involves creating (`create` method) a new instance of muscle in the class `Muscle` and adds it to the database.  Its value is assigned to `new_muscle`.  A unique `id` is assigned to it.  Its attributes are assigned values from the `params` hash (sent by the frontend).  It then converts it to JSON format (serialization) and persists it to the backend with a relative path of `/muscles` using the `to_json` method.

**Read:** the use of `get`

```
    get '/muscles' do
      muscles = Muscle.all.order(:name)
      muscles.to_json
    end
```
This `get` method involves accessing all (`all` method) of the muscles in the table muscles and converting it to an array of instances in alphabetical order (using the `order` method) by the attribute name.  This array is assigned to the variable `muscles`.  It then converts it to JSON format (serialization) and persists it to the backend with a relative path of `/muscles` using the `to_json` method.

**Update:** the use of `patch`

```
    patch '/muscles/:id' do
      updated_muscle = Muscle.find_by(id: params[:id])
      updated_muscle.update(
        origin: params[:origin], 
        insertion: params[:insertion], 
        action: params[:action], 
        innervation: params[:innervation], 
        blood_supply: params[:blood_supply]
      )
      updated_muscle.to_json
    end
```
This `patch` method involves finding an instance of `Muscle` with the `id` value from the `params` hash. The `update` method is used to update that instance of muscle with by assigning attributes values from `params`.  The value of this instance is assigned to `updated_muscle`.  It then converts it to JSON format (serialization) and persists it to the backend with a relative path of `/muscles` using the `to_json` method.

**Delete:** the use of `destroy`

```
    delete '/muscles/:id' do
      muscle = Muscle.find(params[:id])
      muscle.destroy
      muscle.to_json
    end
```
This `delete` method involves finding an instance of `Muscle` with the `id` value from the `params` hash.  This instance is assigned to `muscle`.  It is subsequently deleted from the database using the `destroy` method and serialized using `to_json`.  It is deleted from the backend.

Now we can use CRUD methods to create and manipulate both the database and the server.  Now with a functional React frontend I have created an interactive muscle anatomy chart which looks like this.


![Muscle anatomy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m36lzucbrloeu0innncs.png)

This the power of CRUD combined with a Ruby based Active Record/Sinatra backend and a React frontend.  Thank you.  The CRUD prequel will come soon to bring an end to the trilogy.