Setting up Rails --Api
Tags: rails, architecture, beginners, webdev
Published: 2020-06-01 01:24:50

A good question is: Why would we want a rails Application Programming Interface? Well… you came to the right place. A short quick and simple explanation. An Api serves to maintain, hold and transfer information. Let’s pretend we are a start up and we have a product called tweeter. Tweeter is an application where we can send tweets (thoughts &/or information) on the internet. Now we need a location (databse) to hold our users who sign up and tweet. Our API talks to our database who stores all out information. This is crucial for any application. For now we are involved in the backend (database) and API – (middle backend) of our application.

Continuing with our start up example. We need to set up our rails API. First line of code we need to write is

```rails new tweeter –api```

we of course called our api “tweeter” but you can give it any name you like

```rails new any-name –api```

And that is it, our API is up and running. However, we do not have a database set up. For that we need to create a table and rows of information. It is simple, lets look. So our user here will have a username, email, phone number and a password (we will call it password_digest).

```rails g scaffold User userName email password_digest phoneNum:integer```

```rails g scaffold Tweet content user_id:integer```

On our column, no need to declare it a string, all info is taken as strings, but phone number which are integers must be declared as integers. Booleans & integers must be declared with their corresponding column.

Next we run rails db:migrate and we have our first table, model, controller, but for now we wont worry about our views, we will take a look at associations our next talk.

Do not forget to bundle our gem ‘bcrypt’ it is essential on our Gemfile. Visit our Gemfile and uncomment or add – ```gem bcrypt``` 
Then in our terminal run 
```bundle install``` 
We are closer now to setting up tweeter.



----------------------------------------------------------------


At this point we need to scaffold a table, migrate that table, create our associations, console into our project and create users and tweet. Sound Simple enough? Lets dive in then!

First lets create out “Tweet” table

```rails g scaffold Tweet content user_id:integer```

And we get 


```
class CreateTweets < ActiveRecord::Migration[6.0]

  def change

    create_table :tweets do |t|

      t.string :content

      t.integer :user_id

      t.timestamps

    end

  end

end
```

So now we have a user table and Tweet table and we need to migrate them.


```rails db:migrate```


At this point our controller and model have been set up. 

```
class Tweet < ApplicationRecord
end
```
& 

```
class TweetsController < ApplicationController
  before_action :set_tweet, only: [:show, :update, :destroy]

  # GET /tweets
  def index
    @tweets = Tweet.all

    render json: @tweets
  end

  # GET /tweets/1
  def show
    render json: @tweet
  end

  # POST /tweets
  def create
    @tweet = Tweet.new(tweet_params)

    if @tweet.save
      render json: @tweet, status: :created, location: @tweet
    else
      render json: @tweet.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /tweets/1
  def update
    if @tweet.update(tweet_params)
      render json: @tweet
    else
      render json: @tweet.errors, status: :unprocessable_entity
    end
  end

  # DELETE /tweets/1
  def destroy
    @tweet.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_tweet
      @tweet = Tweet.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def tweet_params
      params.require(:tweet).permit(:content, :user_id)
    end
end
```


This outcome applies to our User table too. However, our models need an association, how would our table look now? Both User and Tweet

```
class User < ApplicationRecord

  has_many :tweets

end
```
&
```
class Tweet < ApplicationRecord

  belongs_to :user
	
  has_secure_password

end
```


What happened here? Well we are bringing in extra methods that can be called upon when we need to derive associated information. Our ‘‘has_secure_password” helps to mantain our password hidden when displaying information, it needs ‘gem bcrypt’ to function. I do need some extra users in the database however, so I’ll dig into the console and add them manually.

```rails c```

then 

```User.create(username: "rocky", phoneNum: 2021234567, email: "rocky@email.com", password_digest: "rocky")```

& a Tweet

```Tweet.create(content: "First tweet!", user_id: 1)```

The user id column is so important, that is where we put the id of the user who creates the Tweet. Now when we run 

```
Tweet.all
```

or 

```
User.all
``` 

in our console and we see we have populated information. To see our data display as json data, we simply go to our localhost and use the routes. Run ```rails s``` in your terminal and In this case we will go to 
```
localhost:3000/users
``` 
& 
```
localhost:3000/tweets
```
in our browser, (yes it has to be plural or according to your routes if changed). All our information we inserted manually should be there waiting for us.

That was not so bad! Next, we will utilize active model serializers to display information that is associated with one another


----------------------------------------------------------------

To setup our Active model serializers we need a few steps. It will be so quick; it will surprise you. Before we start let us look at the data that is presented to us when we initialize our localhost and hit our routes from our backend

```
[
   {
      id: 1,
      username: "rocky",
      phoneNum: 2021234567,
      email: "rocky@email.com",
      password_digest: "rocky"
   }
]
```

Our password is being shared; we do not want that. So, lets fix it. First, we must access our gem files and add our gem.

```gem 'active_models_serializers'```

Then install with 

```bundle install```

Once we have set our gem up, we need to create the serializer objects based on the models we have created.

```rails g serializer User```

```rails g serializer Tweet```

Great. Now we have our serializers:

```
class UserSerializer < ActiveModel::Serializer
  attributes  :id
end
```

Oh no, we have only one attribute on our serializers.

```
[
   {
      id: 1
   }
]
```

Here is where we add or remove our information. Naturally with our routes, our information is being sent through our controllers. But with our serializer we control the data and what is being displayed.

```
 class UserSerializer < ActiveModel::Serializer
  attributes :id,
  	     :username,
             :phoneNum,
             :email
end
```

Fantastic, we now are sending the specific information we want to share and display Our data now looks like this.

```
[
   {
      id: 1,
      username: "rocky",
      phoneNum: 2021234567,
      email: "rocky@email.com",
   }
]
```


A cool trick is to associate data through our serializers, it’s just like creating associations between our models. It looks something like this.

```
[
   {
      id: 1,
      username: "rocky",
      phoneNum: 2021234567,
      email: "rocky@email.com",
      tweets: [
         {
            id: 1,
            content: "My first Tweet",
            user_id: 1
         }
      ]
   }
]
```

How cool is that? We now have finished building Tweeter’s Backend, what an accomplishment!

----------------------------------------------------------------


One last thing, on your Config/Application.rb file you must have your file like this 

```
class Application < Rails::Application
    config.middleware.insert_before 0, Rack::Cors do
      allow do
          origins '*'
          resource '*', headers: :any, methods: [:get, :post, :delete, :patch, :options]
      end
    end
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = true
  end
```
and add the rack CORS gem.

```gem 'rack-cors'```
along with pry if you so desire
```gem 'pry'```

then we bundle install.

Now you are ready to do some Asynchronous calls to your --API

Thoughts? let me know!