Beginner's guide to strong params and validations
Tags: ruby, rails, beginners
Published: 2020-06-01 13:39:41

This is your moment.

You have put your blood, sweat, and tears into configuring Rails to work as an API. You are ready to unveil your API to the world so users can enter their data to be stored in your database.  

Imagine the crowds roar as you roll out the red carpet. Your database is an exclusive club that everyone is dying to become a member of. Every candidate hopefuls must be screened at the door and go through rigorous interview process to earn a coveted membership to your database!

![Alt text of image](https://media.giphy.com/media/3o6Mb4NZeE8yDb5O8w/giphy.gif)

This is where strong params and validations come in. Think of strong params as a screen list written for a bouncer. This list specifies traits that a candidate must exhibit in order to enter the club.

Once the screened candidates enter the club, they are further assessed by an interviewer. Interviewer is given a criteria list(validations) to assess whether the candidates are really who they appear to be. Only when the interviewer deems the candidate to meet the requirements, the candidate is given the membership to your database. 

Ready to raise the standards of granting membership to your database? Let's get started. 

####PREREQUISITE DOWNLOAD: 
We will be using a free tool called Postman to test our strong params and validations. Download [Postman](https://www.postman.com/downloads/)

####Goal
You are tasked with creating a database of top secret spy agents stationed around the world. When your database is integrated with the frontend, the Head of Intelligence Service should be able to view the agent's name, alias, organization, and current location. He/she should also be able to create a record of a new spy agent. 

Your mission should you choose to accept it is to create a database that would save spy agent data ONLY if it meets the following requirements:

1. The database must receive all of the following attributes: name, alias, organization, and current location
2. The alias of spy agent should be unique
3. The alias should be at least four characters long

####Steps to creating an API and setting up strong params and validations
1. Create a new Rails API
2. Enable CORS(Cross Origin Resource Sharing)
3. Create model, controller, database migration table and route via rails g resource command
4. Specify attributes and datatypes of a spy 
5. Define strong params in controller and set up index and create actions 
6. Create routes for index and create actions
7. Fire up your server & postman to test strong params and validations 

####BACKGROUND INFO
You will notice that steps 1-5 of this blog are very similar to steps in my previous blog post:[Beginner's guide to creating an API from scratch using Rails](https://dev.to/lisahjung/beginner-s-guide-to-creating-an-api-from-scratch-using-rails-2eie). 

Background info on these steps have been omitted to focus blog's scope to strong params and validations. If you need further explanation on steps 1-5 or about Postman, check out my previous blog post above. 

####STEP 1: Create a new Rails API
In the directory of your choosing, type the following into your terminal. This command will create a new Rails API named secret_spy_api. 
```Ruby
#in your terminal
rails new secret_spy_api --api
```
Change into secret_spy_api directory and open the API by typing the following into your terminal. 
```Ruby
# in your terminal
cd secret_spy_api

code .
```
####STEP 2: Enable CORS(Cross Origin Resource Sharing)
In the file explorer of your newly created Rails API, expand the following directories to open cors.rb file. 

config>initializers>cors.rb

Then, 
1. Un-comment lines 8-16(NOTE: line numbers may vary but the corresponding code is pasted below for your reference). 
2. On line 10, change the code (origins 'example.com') to (origins '*') as shown below. 
```Ruby
# in config>initializers>cors.rb
# lines 8-16

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'

    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

```
In your file explorer, scroll all the way down and open Gemfile. 
Un-comment line 26, gem 'rack-cors'

```Ruby
# in Gemfile
gem 'rack-cors'
```
In your terminal, run bundle install. 
```Ruby
#in terminal
bundle install
```
####STEP 3: Create model, controller, database migration table and route via rails g resource command
 
Command syntax:
rails g resource (singular form of your model name)

```Ruby
# in terminal
rails g resource Spy
```
You will see that this command has created following files in one swoop! To help you find these files, the file directory is included in the second line. 

1. a model called spy.rb
app>models>spy.rb 

2. a controller called spies_controller.rb app>controllers>spies_controller.rb 

3. a route called routes.rb 
config>routes.rb

4. a database migration table called 20200531204206_create_spies.rb
db>migrate>20200531204206_create_spies.rb

NOTE:20200531204206 is a timestamp that denotes the time and date I have created the migration file. Your file will have a different timestamp. 

####STEP 4: Specify attributes and datatypes of a spy 
In your 20200531204206_create_spies.rb, copy and paste the following:
```Ruby
# in db>migrate>20200531204206_create_spies.rb

class CreateSpies < ActiveRecord::Migration[6.0]
  def change
    create_table :spies do |t|
      t.string :name
      t.string :alias
      t.string :organization
      t.string :current_location
    end
  end
end
```
_Migrate your table_
```ruby
# in your terminal

rails db:migrate
```
You should see the following output in your terminal if migration has been successfully completed.
```ruby
# Message in your terminal

== 20200531204206 CreateSpies: migrating ======================================
-- create_table(:spies)
   -> 0.0021s
== 20200531204206 CreateSpies: migrated (0.0022s) =============================
```
In your db directory, open schema.rb.
You will see that this file now displays your data structure. 
```
# in db>schema.rb
ActiveRecord::Schema.define(version: 2020_05_31_204206) do

  create_table "spies", force: :cascade do |t|
    t.string "name"
    t.string "alias"
    t.string "organization"
    t.string "current_location"
  end

end
```
####STEP 5: Define strong params in controller and set up index and create actions 

Copy and paste the following in your spies_controller.rb .

```ruby
#in app>controllers>spies_controller.rb 

class SpiesController < ApplicationController 
    def index
        @spies = Spy.all
        render json: @spies
    end 

    def create
        @spy = Spy.create(spy_params)
        render json: @spy
    end 

    private

    def spy_params
        params.require(:spy).permit(:name, :alias, :organization, :current_location)
    end 
    
end

```
_Recap_
Remember the bouncer and interviewer analogy mentioned in the beginning of this blog?

The bouncer(controller) for our exclusive club(database) has a strict screen list(strong params) called spy_params. This screen list instructs the bouncer to only let in candidates(data) with resumes that mention certain traits(attributes). The candidates whose resume does not mention these attributes are prevented from entering our club for further interviews. 

####STEP 5: Set up validations in model
```ruby
class Spy < ApplicationRecord
    validates :name, :alias, :organization, :current_location, presence: true
    validates :alias, uniqueness: true
    validates :alias, length: {minimum: 4}
end
```
_Recap_
Once the bouncer lets candidates through the club doors, our interviewer(model) will further assess whether the candidate is worthy of being a member of our club. 

Sure, everybody looks good on paper(he/she has all the attributes specified on strong params), but are these candidates really who they say they are?

The interviewer looks at the criteria list(validations) and examines whether these candidates really meet the criteria that we have specified in validations.
1. Does the candidate embody the following attributes(:name, :alias, :organization, :current_location)?
2. Is the candidate's alias unique?
3. Is the candidate's alias greater than 4 characters? 

If the candidate meets all the criteria, the candidate is accepted into the club(created as an instance in the database).

If not, the candidate is sent home and is not created as an instance in the database. 

#### STEP 6: Create routes for index and create actions

Copy and paste the following in your routes.rb
```ruby
# in config>routes.rb

Rails.application.routes.draw do
  resources :spies, only: [:index, :create]
end

```
####STEP 7: Fire up your server & postman to test strong params and validations. 

Run the following command in your terminal to run your server.
```ruby
#in your terminal
rails s
```
Download and open Postman.

POSTMAN LAYOUT
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9wxdy3lyt4gau4dcgguy.png)

Get, button with red arrow pointing to it is a HTTP method button. If you click on downward facing arrow, you will see drop down options for other HTTP methods. We will be using POST HTTP method to test our strong params and validations. 

URL, a gray bar with a blue arrow pointing to it is where we will enter the URL of our API server.

Send, a blue button with green arrow pointing to it will be pressed to send the info to our backend to get a response.

**TEST CREATE ACTION**
Create action enables API to create a new instance of our secret spy API. 

Create responds to HTTP Method POST.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/bcwluntyumg8ltzkvipj.png)

**The numbers in the image corresponds to the numbered steps listed below.**
 
**Note: I had trouble uploading images to Dev.to. All uploaded images look a bit blurry so I have copied and pasted the data input and response separately so you can see it clearly.**

In Postman
1.Set HTTP Method to POST
2.Enter request URL of http://localhost:3000/spies
3.Select Body
4.Select raw
5.Select JSON
6.Create a spy object with spy as a top level key and list attributes of a new spy agent you want to create. By requiring a top level key, strong params provide additional security. 
```ruby
{
	"spy": {
		"name": "Charles Beddington",
		"alias": "Phantom Chaser",
		"organization": "MI6",
		"current_location": "Tel Aviv, Israel"
	}
}
```
7. Click send
8. You will see that Postman returns a spy object with an id of 1. This means that the instance of spy Charles Beddington has been successfully created in our database. 

```ruby
{
    "id": 1,
    "name": "Charles Beddington",
    "alias": "Phantom Chaser",
    "organization": "MI6",
    "current_location": "Tel Aviv, Israel"
}
```
** TEST STRONG PARAMS AND VALIDATIONS**
We have set strong params and validations so that an instance of a spy can be created ONLY if :
1. name, alias, organization, and current location attributes are present
2. alias is unique
3. alias is longer than four characters. 

So let's put it to the test!

_Test 1: Omit one of the attributes_
Let's purposefully omit the organization of a new spy agent's data input and see what happens.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rbfjhrgzbodiaylvr1e7.png)

Data input:
```ruby
{
	"spy": {
		"name": "Gracie Hart",
		"alias": "Gracie Lou Freebush,
		"current_location": "San Antonio, Texas"
	}
}
```
Response:
```ruby
{
    "id": null,
    "name": "Gracie Hart",
    "alias": "Gracie Lou Freebush,
    "organization": "null",
    "current_location": "San Antonio, Texas"
}
```
You will see that both the id and organization returns as null. This means that the database refused to create an instance for Agent Gracie Lou Freebush as we failed to include all info required to create an instance.

Once you include the organization info and send the post request again, you will see that Agent Gracie Lou Freebush has been successfully saved to the database with an id number of 2. 

_Test 2: Enter the same alias for a different instance of spy agent_

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/44rrsz2x6012fnhywfjk.png)
Data Input: 
```ruby

{
	"spy": {
		"name": "Margarete Gertrud Zelle",
		"alias": "Gracie Lou Freebush",
		"organization": "German Secret Service",
		"current_location": "Paris, France"
	}
}
```
Response:
```ruby
{
    "id": null,
    "name": "Margarete Gertrud Zelle",
    "alias": "Gracie Lou Freebush",
    "organization": "German Secret Service",
    "current_location": "Paris, France"
}
```
We sent data input about a new spy agent but with the same alias as the one we have created prior. As you can see, the request returned an object with an id of null which means that the new spy agent data failed to be saved in the database. 

_Test 3: Enter an alias with less than four characters_

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0k8sbxxfa5evmbwbrj2o.png)
Data input: 
```ruby
{
	"spy": {
		"name": "Margarete Gertrud Zelle",
		"alias": "2",
		"organization": "German Secret Service",
		"current_location": "Paris, France"
	}
}
```
Response:
```ruby
{
    "id": null,
    "name": "Margarete Gertrud Zelle",
    "alias": "2",
    "organization": "German Secret Service",
    "current_location": "Paris, France"
}
```
You will see that when we enter alias with less than 4 characters, the response returns an object with id of null. The new agent did not get saved in our database. 

If you fix the data input so that all attributes are present, alias is unique and is longer than four characters, you will see that it successfully saves a new spy agent!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dt3ezkci59az1oxt6o0p.png)

Congratulations. You have successfully set up strong params and validations in the secret spy database by following these 7 steps:

1. Create a new Rails API
2. Enable CORS(Cross Origin Resource Sharing)
3. Create model, controller, database migration table and route via rails g resource command
4. Specify attributes and datatypes of a spy 
5. Define strong params in controller and set up index and create actions 
6. Create routes for index and create actions
7. Fire up your server & postman to test strong params and validations

This message will self destruct in five seconds. 
![Alt text of image](https://media.giphy.com/media/j6FB2neMBtFVC/giphy.gif)