& PHOENIX FRAMEWORK
PROGRAMMING LANGUAGE
Elixir is a dynamic, functional language designed for building scalable and maintainable applications.
WRITE SOME ELIXIR
REALTIME WEB
Request
Response
Browser/Client
Server
Connect
Data/Payload
Browser/Client
Server
MVC WEB APPLICATION FRAMEWORK
defmodule MvcExampleWeb.UserController do
use MvcExampleWeb, :controller
alias MvcExample.Accounts
alias MvcExample.Accounts.User
def index(conn, _params) do
users = Accounts.list_users()
render(conn, "index.html", users: users)
end
def new(conn, _params) do
changeset = Accounts.change_user(%User{})
render(conn, "new.html", changeset: changeset)
end
enddefmodule MvcExample.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
alias MvcExample.Accounts.User
schema "users" do
field :age, :integer
field :name, :string
timestamps()
end
@doc false
def changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:name, :age])
|> validate_required([:name, :age])
end
end<%= form_for @changeset, @action, fn f -> %>
<div class="form-group">
<%= label f, :name, class: "control-label" %>
<%= text_input f, :name, class: "form-control" %>
<%= error_tag f, :name %>
</div>
<div class="form-group">
<%= label f, :age, class: "control-label" %>
<%= number_input f, :age, class: "form-control" %>
<%= error_tag f, :age %>
</div>
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>defmodule MvcExampleWeb.Router do
use MvcExampleWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
scope "/", MvcExampleWeb do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
# Users resoruceful endpoints
resources "/users", UserController
end
enddefmodule MvcExample.Repo.Migrations.CreateUsers do
use Ecto.Migration
def change do
create table(:users) do
add :name, :string
add :age, :integer
timestamps()
end
end
end# Generates a Phoenix channel
mix phx.gen.channel
# Generates a context with functions around an Ecto schema
mix phx.gen.context
# Generates an embedded Ecto schema file
mix phx.gen.embedded
# Generates controller, views, and context for an HTML resource
mix phx.gen.html
# Generates controller, views, and context for a JSON resource
mix phx.gen.json
# Generates a Presence tracker
mix phx.gen.presence
# Generates an Ecto schema and migration file
mix phx.gen.schema defmodule MvcExample.AccountsTest do
use MvcExample.DataCase
alias MvcExample.Accounts
describe "users" do
alias MvcExample.Accounts.User
test "list_users/0 returns all users" do
{:ok, user} =
attrs
|> Enum.into(%{age: 42, name: "some name"})
|> Accounts.create_user()
assert Accounts.list_users() == [user]
end
end
end
defmodule Chat.RoomChannel do
use Phoenix.Channel
def join("rooms:lobby", message, socket) do
send(self, {:after_join, message})
{:ok, socket}
end
def handle_in("new:msg", msg, socket) do
broadcast! socket, "new:msg", %{user: msg["user"], body: msg["body"]}
{:reply, {:ok, %{msg: msg["body"]}}, assign(socket, :user, msg["user"])}
end
def handle_info({:after_join, msg}, socket) do
broadcast! socket, "user:entered", %{user: msg["user"]}
push socket, "join", %{status: "connected"}
{:noreply, socket}
end
endWRITE THE CODE
WRITE COPY/PASTE THE CODE
IN 10 MINUTES
mix phx.new chat --no-ecto
cd chat
cd assets
yarn
cd ..
mix phx.server# lib/chat_web/templates/page/index.html.eex
<!-- The list of messages will appear here: -->
<ul id='msg-list' class='row' style='list-style: none; min-height:200px; padding: 10px;'></ul>
<div class="row">
<div class="col-xs-3">
<input type="text" id="name" class="form-control" placeholder="Your Name" autofocus>
</div>
<div class="col-xs-9">
<input type="text" id="msg" class="form-control" placeholder="Your Message">
</div>
</div>mix phx.gen.channel Room# lib/chat_web/channels/user_socket.ex
defmodule ChatWeb.UserSocket do
use Phoenix.Socket
## Channels
channel "room:lobby", ChatWeb.RoomChannel
# ...
end# assets/js/app.js
import socket from "./socket"
// connect to chat "room"
var channel = socket.channel('room:lobby', {});
// listen to the 'shout' event
channel.on('shout', function (payload) {
var li = document.createElement("li");
var name = payload.name || 'guest';
li.innerHTML = '<b>' + name + '</b>: ' + payload.message;
ul.appendChild(li);
});
// join the channel.
channel.join();
var ul = document.getElementById('msg-list');
var name = document.getElementById('name');
var msg = document.getElementById('msg');
// "listen" for the [Enter] keypress event to send a message:
msg.addEventListener('keypress', function (event) {
if (event.keyCode == 13 && msg.value.length > 0) {
channel.push('shout', {
name: name.value,
message: msg.value
});
msg.value = '';
}
});FROM THE AUDIENCE
FOR YOUR ATTENTION