Skip to content

Instantly share code, notes, and snippets.

@alanpeabody
Last active August 29, 2015 14:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alanpeabody/d03f3788a0c851a36ca3 to your computer and use it in GitHub Desktop.
Save alanpeabody/d03f3788a0c851a36ca3 to your computer and use it in GitHub Desktop.
Web apps in elixir

Web apps in Elixir

The database

Ecto

Database lib/DSL currently targeting PostgreSQL.

Alternatives

  • ETS: In memory key/value store (w/ some nice apis).
  • DETS: Disk based key/value store (w/ some nice apis).
  • Mnesia: Disk & Memory based advanced key/value store w/ very nice apis.

Handling Requests

Cowboy

An erlang web server, think of it like a highly performant unicorn/puma/mongrel.

Don't need to know much about it, besides that it is there. Currently websockets must be interfaced directly via cowboy if not using Phoenix.

Plug

A Rack/Ring like library for building composeable web applications. Currently only runs on cowboy.

Some cool stuff:

The connection

Plug uses a "struct", Plug.Conn, that is used to maintain state. This starts as the incoming request, you then pass it through one or more functions which add or set properties on the conn. Eventually you respond to the request.

import Plug.Conn #gives us methods used below.
current_user = User.find(conn.params["user_id"])
conn = assigns(conn, :current_user, current_user)
#...
if conn.assigns[:current_user]
  send_resp(conn, 200, "text to respond with")
else
  halt send_resp(conn, 401, "nope.")
end

A "plug" is a stack of functions that accepts a connection and returns a connection.

defmodule MyApp.Router do
  use Plug.Router
  
  plug :set_current_user
  plug :require_current_user, only: ["v1/top_secret"]
  plug :match    #from plug.router
  plug :dispatch #from plug.router
  
  def set_current_user(conn, _opts) do
    case User.find(conn.params["user_id"]) do
      nil  -> conn
      user -> assigns(conn, :current_user, user)
    end
  end
  
  def require_current_user(conn, opts) do
    case Enum.any? opts[:only] &(String.split(&1, "/") == conn.path) do
      false -> conn #not in only clause, just continue
      true  -> 
        # yo dawg, I heard you liked case statements....
        case conn.assigns[:current_user] do
          nil  -> halt send_resp(conn, 401, "nope")
          user -> conn
        end
    end
  end

   get "v1/top_secret" do
      
   end
   
   def match(conn) do
     do_match(conn.method, conn.path, conn)
   end
   
   def do_match("GET", ["v1","top_secret"], conn) do
     
   end
end

"Frameworks"

Relax

:-D :-D :-D :-D

Next steps:

  • Ensure blog still works (WIP)
  • Build an actual real (simple) app including Ember.js front end.
  • Figure out how to integrate with Phoenix (call from view probably, but maybe via controller).
  • Document all relevant modules and functions.
  • Publish to hex.pm
  • Announce on mailing list?
  • ...
  • Use in client app????

Phoenix

Rails inspired framework in Elixir. Getting lots of attention recently. Benchmarks suggest in some cases it is one order of magnitude faster then the same app in rails.

Has full Router, Controller, View, Template system, but expects you to BYO Model. Also features "Channels" which are like controllers for websockets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment