How to REST

How to Series

REST, branch, Rails, Start, Single Sign On, Deploy, Continuous Deployment, Report Issue, ...

 

DHH: The missing part

AHA moment

Problems

  • Lack of constraints
  • When should I introduce new controller?
  • Where should I put new action?
  • How much action should do?

Representational State Transfer

REST systems interface with external systems as web resources identified by Uniform Resource Identifiers (URIs)

What is Resource?

Database table

Never ever even if looks similar

{
  "id": 1,
  "projects": [
    {
      "id": 13,
      "name": "Projekt"
    },
    {
      "id": 15,
      "name": "Inny projekt"
    }
  ],
  "birthdate": "19.03.2003",
  "name": "Guess Who"
}

GraphQL vs REST

Premature optimization

You can nest resources

but don't from day 1

Fun fact

REST is easy

Use only basic actions

  • index
  • show
  • update
  • new
  • create
  • destroy
  • edit

New action

==

Think about resources

Examples

Current user

class CurrentUsersController < ApplicationController
  def show
    # ...
  end
end

# or

module Users
  class CurrentsController < ApplicationController
    def show
      # ...
    end
  end
end

Choose picture

module Api
  module V1
    class PicturesController < Api::V1::BaseController
      def choose
        # ...
      end
    end
  end
end

Choose picture

module Api
  module V1
    class PicturesController < Api::V1::BaseController
      class Selected < Api::V1::BaseController
        def create
          # ...
        end
      end
    end
  end
end

User groups

class API::V3::Main::Groups < Grape::API
  include API::V3::Main::Defaults
  include Grape::Kaminari

  resource :groups do
    paginate
    params do
      requires :user_id, type: Integer, desc: "User ID"
    end
    get "user/:user_id" do
      # ...
    end
  end
end

User groups

class API::V3::Main::Users::Groups < Grape::API
  include API::V3::Main::Defaults
  include Grape::Kaminari

  resource :users do
    params do
      requires :id, type: Integer, desc: "User ID"
    end
    namespace ":id/groups" do
      get "/" do
        # like index action
      end
    end
  end
end

Get title

module API
  module V1
    class Findings < Grape::API
      include API::V1::Defaults
      include Grape::Kaminari

      resources :findings do
        params do
          requires :link, type: String
        end
        get "get_title" do
          # ...
        end
      end
    end
  end
end

Get title

Title # resource
show # get_title

Resend

module Api
  class CrewMembersController < ApplicationController
    before_action :doorkeeper_authorize!
    before_action :authenticate!
    before_action :require_company

    api :POST, '/crew_members/:id/resend', 'Resend a crew invitation email'
    param :id, :uuid, required: true
    def resend
      # ...
    end
  end
end

Resend

Invitation # resource
create # create (and probably send) new one

# alternative e.g. for different logic

Reminder, Reinvitation, ... ?

Why?

  • Less confusion
  • Improve domain understanding
  • Simpler code

Resource?

(...) information that can be named (...)

 

A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time.

Questions?

http://jeromedalbert.com/how-dhh-organizes-his-rails-controllers/


https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling


http://www.restapitutorial.com/lessons/restfulresourcenaming.html

Made with Slides.com