How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes

This guide is multi-use, designed for passing a code challenge but could be useful for jumping into a new codebase, or refreshing your knowledge of ruby on rails, or getting a brief overview of how an MVC (Model View Controller) framework works!

1) C…


This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Elliot Mangini

This guide is multi-use, designed for passing a code challenge but could be useful for jumping into a new codebase, or refreshing your knowledge of ruby on rails, or getting a brief overview of how an MVC (Model View Controller) framework works!

1) Commands

$ bundle install
$ npm install --prefix client

2) Generators

$ rails g scaffold lowercase_snake_formatted_name attr_default_string attr_of_type:datatype model_that_has_many_of_these:belongs_to --no-test-framework

Lowercase snake is is the only format that will turn test_model into TestModel, TestModels, has_many :test_models, etc in all the right places.

Pay attention to using belongs_to relationships in this generator as it will create the foreign key tables. We won’t need to use has_many in this line ever because of the nature of where foreign keys live.

If you make a mistake . . .

$ rails destroy scaffold scaffold_to_destroy

3) Fill out model relationships

belongs_to will be created automatically
has_many will be created like so . . .

    has_many :signups, dependent: :destroy
    has_many :campers, through: :signups

This is a good time to consider dependent: :destroy if applicable.

4) Fill out model validations

Here are some common ones . . .

    validates :name, presence: true
    validates :age, :inclusion => 8..18
    validates :email, :uniqueness: true

5) Seed

$ rails db:migrate db:seed

6) routes.rb - Fill it out correctly

If all routes are required we use

resources :model

Otherwise the following paths correspond to the following only: array symbols
GET /models => [ . . . , :index]
GET /models/:id => [ . . . , :show]
POST /models => [ . . . , :create]
PATCH /models/:id => [ . . . , :update]
DELETE /models/:id => [ . . . , :destroy]

Altogether we end up with something like . . .

resources :models, only: [:index, :show, :create]

~) As you do the following be mindful of what routes you need, or perhaps do ALL of the steps if unsure . . .

7) Clean Up Tasks

In any controllers that take params . . .

params.require(:model).permit(:attr1, :attr2)

…becomes . . .

params.permit(:attr1, :attr2)

…to be safe we can also add to the TOP of each of these controllers . . .

wrap_parameters format: []

We can also deal with RecordNotFound errors that will be triggered by any of the above methods a single time in application_controller.rb
We add the following . . .

  rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_response

  private

  def render_not_found_response(exception)
    render json: { error: "#{exception.model} not found" }, status: :not_found
  end

In Controllers, add bang operator ! to create and update methods if they are going to be used.

def create
  @model = Model.new(model_params)

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

…becomes . . .

def create
  @model = Model.create!(model_params)
  render json: @model, status: :created
end

Likewise the update methods are adjusted the same way.

def update
  if @model.update(model_params)
    render json: @model
  else
    render json: @model.errors, status: :unprocessable_entity
  end
end

…becomes as simple as . . .

def update
  @model.update!(model_params)
  render json: @model, status: :accepted
end

Add head :no_content to destroy routes

def destroy
  @activity.destroy
end

…becomes . . .

def destroy
  @activity.destroy
  head :no_content
end

8) Add unprocessable_entity errors where needed

If we have a POST or UPDATE path in use for a model (create or update methods) we also must add to our private methods inside the controller . . .

def render_unprocessable_entity_response(invalid)
  render json: { errors: invalid.record.errors.full_messages }, status: :unprocessable_entity
end

…since these methods take parameters (strong) and at the TOP of this controller we must add . . .

rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity_response

This must be in place in each controller where POST or UPDATE are in use.

9) Special Concerns

The “Instead Of” case: When a user signs up for a signup instead of returning the signup we want to return what they signed up for. This is very easy we do the following for example . . .

def create
  @signup = Signup.create!(signup_params)
  render json: @signup, status: :created
end

…becomes . . .

def create
  @signup = Signup.create!(signup_params)
  render json: @signup.activity, status: :created
end

@signup => @signup.activity

We can also solve this by creating a new serializer, but we don’t always need to. If it’s a wickedly simple replace the instance with an associated instance that is formatted using the default serializer we can do it like the above.

In other words we are returning the default-formatted associated model instance of interest instead of the one being operated on.

Return All Associated Instances case: I have a user with many tickets, when I show method/route on this user I want their tickets to be returned as children. As long as model relationships and db are associated properly this is as simple as adding to the UserSerializer the following line . . .
has_many :tickets

The tickets will be formatted using the default TicketSerializer.

It’s good to note here that if we have a many-to-many relationship like a doctor who has many patients through appointments we can return the patients the same way using directly a has_many :patients and the serializer should know to jump over the join table.

But Only Sometimes case: What if I don’t want the tickets to come through on an index method/route when we see all the users and instead only when we see just one? Instead of modifying the main serializer, in this case UserSerializer we can make a new one . . .

$ rails g serializer user_show_tickets

Since this serializer wasn’t scaffolded we need to make sure we add the appropriate main attributes at the top. They can be copied from the regular UserSerializer as long as we want them . . .

attributes :id, :name, :age, :email

Then we add the has_many here instead of in the UserSerializer. Altogether it looks something like . . .

class UserShowTicketsSerializer < ActiveModel::Serializer
  attributes :id, :name, :age, :email
  has_many :tickets
end

Finally, we specify that this method/route uses this serializer inside the controller where it is declared. . .

def show
  render json: @user, serializer: UserShowTicketsSerializer
end

We can specify a serializer to do anything on a specific route this way, however it’s important to note that inside a serializer we have access to the instance by calling it object if we want to access specific properties of it.

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

10) Troubleshooting

If we are using @model instance methods or a set/find private method throughout our controllers this is a good clue that we should include a line like the following at the top of the controller if we want to use that variable directly. Scaffolding takes care of this automatically, but in case it’s helpful . . .

before_action :set_instance, only: [:show, :update, :destroy]

Here we are saying we need to set this variable when we use the following method-routes (the ones that depend on using that variable).

If we are using the server and npm to test instead of using tests it might become critical to clear our database on re-testing in case bad data was passed into the db along the way of getting our code working . . . we can add the following to our seeds.rb . . . (above the create invocations)

puts "Clearing database"
ModelOne.destroy_all
ModelTwo.destroy_all
ModelThree.destroy_all

Now, our

$ rails db:seed

works a lot like a replant.

BONUS) Comment out or remove routes in the controllers that aren’t being used.

Hope this is helpful, let me know if I missed anything or made errors!
-Elliot/Big Sis


This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Elliot Mangini


Print Share Comment Cite Upload Translate Updates
APA

Elliot Mangini | Sciencx (2022-10-19T19:20:28+00:00) How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes. Retrieved from https://www.scien.cx/2022/10/19/how-to-create-a-ruby-on-rails-api-with-scaffold-full-10-step-guide-in-5-minutes/

MLA
" » How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes." Elliot Mangini | Sciencx - Wednesday October 19, 2022, https://www.scien.cx/2022/10/19/how-to-create-a-ruby-on-rails-api-with-scaffold-full-10-step-guide-in-5-minutes/
HARVARD
Elliot Mangini | Sciencx Wednesday October 19, 2022 » How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes., viewed ,<https://www.scien.cx/2022/10/19/how-to-create-a-ruby-on-rails-api-with-scaffold-full-10-step-guide-in-5-minutes/>
VANCOUVER
Elliot Mangini | Sciencx - » How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/10/19/how-to-create-a-ruby-on-rails-api-with-scaffold-full-10-step-guide-in-5-minutes/
CHICAGO
" » How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes." Elliot Mangini | Sciencx - Accessed . https://www.scien.cx/2022/10/19/how-to-create-a-ruby-on-rails-api-with-scaffold-full-10-step-guide-in-5-minutes/
IEEE
" » How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes." Elliot Mangini | Sciencx [Online]. Available: https://www.scien.cx/2022/10/19/how-to-create-a-ruby-on-rails-api-with-scaffold-full-10-step-guide-in-5-minutes/. [Accessed: ]
rf:citation
» How To Create A Ruby On Rails API With Scaffold – Full 10 Step Guide In 5 Minutes | Elliot Mangini | Sciencx | https://www.scien.cx/2022/10/19/how-to-create-a-ruby-on-rails-api-with-scaffold-full-10-step-guide-in-5-minutes/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.