Snapi

Section 2

App and Routing

App

Responsibilities

  1. Grabbing the web request by verb and route
  2. Creating a default response
  3. Sending it to the curator
  4. Serializing the response to JSON
  5. Returning the serialized response

Concepts

  • BaseApp
  • verb and route
  • response
  • curate
  • artifact
  • serialize
class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
  include Omicron.serialization(ContactSerializer)

  get "/contacts" do
    pipe(default_response, :through => [
      :serialize
    ])
  end

  get "/contacts/search" do
    response = curate(artifact, :action => :search)
    serialize(response)
  end

  get "/contacts/:id" do |id|
    response = curate(artifact, :action => :show)
    serialize(response)
  end

  post "/contacts" do
    response = curate(artifact, :action => :create)
    serialize(response)
  end

  %i(patch put).each do |verb|
    send(verb, "/contacts/:id") do |id|
      response = curate(artifact, :action => :update)
      serialize(response)
    end
  end

  delete "/contacts/:id" do |id|
    response = curate(artifact, :action => :delete)
    serialize(response)
  end
end

BaseApp

  • BaseApp < Omicron::App
  • Omicron::App < Sinatra::App
  • Provides functions like
    • default_response​
    • authenticate
    • authentication_response
    • identity_map
    • artifact
    • current_user
    • template

verb and route

get "/contacts" 

get "/contacts/search" 

get "/contacts/:id" 

post "/contacts" 

%i(patch put).each do |verb|
  send(verb, "/contacts/:id") do |id|

delete "/contacts/:id"
class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
  include Omicron.serialization(ContactSerializer)

  get "/contacts" do
    pipe(default_response, :through => [
      :serialize
    ])
  end

  get "/contacts/search" do
    response = curate(artifact, :action => :search)
    serialize(response)
  end

  get "/contacts/:id" do |id|
    response = curate(artifact, :action => :show)
    serialize(response)
  end

  post "/contacts" do
    response = curate(artifact, :action => :create)
    serialize(response)
  end

  %i(patch put).each do |verb|
    send(verb, "/contacts/:id") do |id|
      response = curate(artifact, :action => :update)
      serialize(response)
    end
  end

  delete "/contacts/:id" do |id|
    response = curate(artifact, :action => :delete)
    serialize(response)
  end
end

response

Returns an initialization response

class Response
  include Virtus.value_object

  values do
    attribute :status, Integer, :default => 200
    attribute :headers, Hash, :default => {}
    attribute :collection, Array, :default => []
    attribute :original_collection, Array, :default => []
    attribute :page_information, Hash
    attribute :error_message, String
  end
end
class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
  include Omicron.serialization(ContactSerializer)

  get "/contacts" do
    pipe(default_response, :through => [
      :serialize
    ])
  end

  get "/contacts/search" do
    response = curate(artifact, :action => :search)
    serialize(response)
  end

  get "/contacts/:id" do |id|
    response = curate(artifact, :action => :show)
    serialize(response)
  end

  post "/contacts" do
    response = curate(artifact, :action => :create)
    serialize(response)
  end

  %i(patch put).each do |verb|
    send(verb, "/contacts/:id") do |id|
      response = curate(artifact, :action => :update)
      serialize(response)
    end
  end

  delete "/contacts/:id" do |id|
    response = curate(artifact, :action => :delete)
    serialize(response)
  end
end

curate

This is a function added to our app by the ContactCurator through the include magic of Omicron.curation.

class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
end

We can now call curate in our app. This will call search_action in ContactCurator.

get "/contacts/search" do
  response = curate(artifact, :action => :search)
  serialize(response)
end
class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
  include Omicron.serialization(ContactSerializer)

  get "/contacts" do
    pipe(default_response, :through => [
      :serialize
    ])
  end

  get "/contacts/search" do
    response = curate(artifact, :action => :search)
    serialize(response)
  end

  get "/contacts/:id" do |id|
    response = curate(artifact, :action => :show)
    serialize(response)
  end

  post "/contacts" do
    response = curate(artifact, :action => :create)
    serialize(response)
  end

  %i(patch put).each do |verb|
    send(verb, "/contacts/:id") do |id|
      response = curate(artifact, :action => :update)
      serialize(response)
    end
  end

  delete "/contacts/:id" do |id|
    response = curate(artifact, :action => :delete)
    serialize(response)
  end
end

Curator

Curator is where we handle all of our business logic.

The curate function takes the action and calls a function in the Curator provided by the Omicron.curation. It converts :action => :show into a call to show_action in the Curator provided.

artifact

class Mufasa::Artifact
  include Virtus.value_object
  
  values do
    attribute :success, Boolean, :default => true
    attribute :params, Hash, :default => {}
    attribute :authentication_response, Object
    attribute :remote_ip, Object
    attribute :user_agent, Object
    attribute :oauth_application, Object
  end
end

An artifact is a way to send current web request context into the curator 

class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
  include Omicron.serialization(ContactSerializer)

  get "/contacts" do
    pipe(default_response, :through => [
      :serialize
    ])
  end

  get "/contacts/search" do
    response = curate(artifact, :action => :search)
    serialize(response)
  end

  get "/contacts/:id" do |id|
    response = curate(artifact, :action => :show)
    serialize(response)
  end

  post "/contacts" do
    response = curate(artifact, :action => :create)
    serialize(response)
  end

  %i(patch put).each do |verb|
    send(verb, "/contacts/:id") do |id|
      response = curate(artifact, :action => :update)
      serialize(response)
    end
  end

  delete "/contacts/:id" do |id|
    response = curate(artifact, :action => :delete)
    serialize(response)
  end
end

serialize

This is a function added by ContactSerializer that will take a response and convert it to JSON.

class ContactApp < BaseApp
  include Omicron.serialization(ContactSerializer)
end

We can now call serialize in our app.

get "/contacts/search" do
  response = curate(artifact, :action => :search)
  serialize(response)
end

App

Responsibilities

  1. Grabbing the web request by verb and route
  2. Creating a default response
  3. Sending it to the curator
  4. Serializing the response to JSON
  5. Returning the serialized response
class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
  include Omicron.serialization(ContactSerializer)

  get "/contacts" do
    pipe(default_response, :through => [
      :serialize
    ])
  end

  get "/contacts/search" do
    response = curate(artifact, :action => :search)
    serialize(response)
  end

  get "/contacts/:id" do |id|
    response = curate(artifact, :action => :show)
    serialize(response)
  end

  post "/contacts" do
    response = curate(artifact, :action => :create)
    serialize(response)
  end

  %i(patch put).each do |verb|
    send(verb, "/contacts/:id") do |id|
      response = curate(artifact, :action => :update)
      serialize(response)
    end
  end

  delete "/contacts/:id" do |id|
    response = curate(artifact, :action => :delete)
    serialize(response)
  end
end

Routing

Setting up routing:

  1. Routes
    • ​Sets up the app where the web request should go
  2. Register Endpoint Helper
    • ​Helps generate urls for serialization
  3. ​Add to PUBLIC_ENDPOINTS
    • ​​constants.rb

Routes

Apiv3::Application.routes.draw do
  root :to => RootApp

  get "/me" => MeApp

  OmicronResource(:contacts, :collection => [:search])

  OmicronResource(
    :countries,
    :collection => [:all, :search],
    :except => [:create, :update, :delete]
  )

  post "/divisions/create_root" => DivisionApp,
    :as => :create_root

  match "/404" => ErrorApp, :via => ErrorApp::VERBS
  match "/500" => ErrorApp, :via => ErrorApp::VERBS
end
class ContactApp < BaseApp
  include Omicron.curation(ContactCurator)
  include Omicron.serialization(ContactSerializer)

  get "/contacts" do
    pipe(default_response, :through => [
      :serialize
    ])
  end

  get "/contacts/search" do
    response = curate(artifact, :action => :search)
    serialize(response)
  end

  get "/contacts/:id" do |id|
    response = curate(artifact, :action => :show)
    serialize(response)
  end

  post "/contacts" do
    response = curate(artifact, :action => :create)
    serialize(response)
  end

  %i(patch put).each do |verb|
    send(verb, "/contacts/:id") do |id|
      response = curate(artifact, :action => :update)
      serialize(response)
    end
  end

  delete "/contacts/:id" do |id|
    response = curate(artifact, :action => :delete)
    serialize(response)
  end
end

Register Endpoint Helper

module RegisterEndpointsHelper
  include Omicron.endpoint

  register_endpoint :contacts, :collection => [:search]
  register_endpoint :countries, :collection => [:search]
  register_endpoint :divisions, :collection => [
    :search, :ancestors, :descendants, :children, :leaves,
    :tree, :create_root, :update_plan, :active_trials, 
    :active, :enable, :disable
  ]
end

Generates _url paths for serializers.
i.e. contacts_url, search_contacts_url

PUBLIC_ENDPOINTS

constants.rb

PUBLIC_ENDPOINTS =
  [
    "apn_devices",
    "assignments",
    "availabilities",
    "broadcast_email_attachments",
    "broadcast_emails",
    "contacts"
   ]

Allows the endpoint to be publicly accessible.

 

Thank you!

Made with Slides.com