Permalink
Browse files

Create Room api endpoints

  • Loading branch information...
bnhansn committed Oct 21, 2016
1 parent 10ee072 commit 2fef1fd7d8710b12389226a30d53c4d42097d5ae
@@ -0,0 +1,14 @@
defmodule Sling.Repo.Migrations.CreateRoom do
use Ecto.Migration
def change do
create table(:rooms) do
add :name, :string, null: false
add :topic, :string, default: ""
timestamps()
end
create unique_index(:rooms, [:name])
end
end
@@ -0,0 +1,15 @@
defmodule Sling.Repo.Migrations.CreateUserRoom do
use Ecto.Migration
def change do
create table(:user_rooms) do
add :user_id, references(:users, on_delete: :nothing), null: false
add :room_id, references(:rooms, on_delete: :nothing), null: false
timestamps()
end
create index(:user_rooms, [:user_id])
create index(:user_rooms, [:room_id])
create index(:user_rooms, [:user_id, :room_id], unique: true)
end
end
@@ -0,0 +1,61 @@
defmodule Sling.RoomControllerTest do
use Sling.ConnCase
alias Sling.Room
@valid_attrs %{name: "some content", topic: "some content"}
@invalid_attrs %{}
setup %{conn: conn} do
{:ok, conn: put_req_header(conn, "accept", "application/json")}
end
test "lists all entries on index", %{conn: conn} do
conn = get conn, room_path(conn, :index)
assert json_response(conn, 200)["data"] == []
end
test "shows chosen resource", %{conn: conn} do
room = Repo.insert! %Room{}
conn = get conn, room_path(conn, :show, room)
assert json_response(conn, 200)["data"] == %{"id" => room.id,
"name" => room.name,
"topic" => room.topic}
end
test "renders page not found when id is nonexistent", %{conn: conn} do
assert_error_sent 404, fn ->
get conn, room_path(conn, :show, -1)
end
end
test "creates and renders resource when data is valid", %{conn: conn} do
conn = post conn, room_path(conn, :create), room: @valid_attrs
assert json_response(conn, 201)["data"]["id"]
assert Repo.get_by(Room, @valid_attrs)
end
test "does not create resource and renders errors when data is invalid", %{conn: conn} do
conn = post conn, room_path(conn, :create), room: @invalid_attrs
assert json_response(conn, 422)["errors"] != %{}
end
test "updates and renders chosen resource when data is valid", %{conn: conn} do
room = Repo.insert! %Room{}
conn = put conn, room_path(conn, :update, room), room: @valid_attrs
assert json_response(conn, 200)["data"]["id"]
assert Repo.get_by(Room, @valid_attrs)
end
test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do
room = Repo.insert! %Room{}
conn = put conn, room_path(conn, :update, room), room: @invalid_attrs
assert json_response(conn, 422)["errors"] != %{}
end
test "deletes chosen resource", %{conn: conn} do
room = Repo.insert! %Room{}
conn = delete conn, room_path(conn, :delete, room)
assert response(conn, 204)
refute Repo.get(Room, room.id)
end
end
@@ -0,0 +1,18 @@
defmodule Sling.RoomTest do
use Sling.ModelCase
alias Sling.Room
@valid_attrs %{name: "some content", topic: "some content"}
@invalid_attrs %{}
test "changeset with valid attributes" do
changeset = Room.changeset(%Room{}, @valid_attrs)
assert changeset.valid?
end
test "changeset with invalid attributes" do
changeset = Room.changeset(%Room{}, @invalid_attrs)
refute changeset.valid?
end
end
@@ -0,0 +1,18 @@
defmodule Sling.UserRoomTest do
use Sling.ModelCase
alias Sling.UserRoom
@valid_attrs %{}
@invalid_attrs %{}
test "changeset with valid attributes" do
changeset = UserRoom.changeset(%UserRoom{}, @valid_attrs)
assert changeset.valid?
end
test "changeset with invalid attributes" do
changeset = UserRoom.changeset(%UserRoom{}, @invalid_attrs)
refute changeset.valid?
end
end
@@ -0,0 +1,55 @@
defmodule Sling.RoomController do
use Sling.Web, :controller
alias Sling.Room
plug Guardian.Plug.EnsureAuthenticated, handler: Sling.SessionController
def index(conn, _params) do
rooms = Repo.all(Room)
render(conn, "index.json", rooms: rooms)
end
def create(conn, params) do
current_user = Guardian.Plug.current_resource(conn)
changeset = Room.changeset(%Room{}, params)
case Repo.insert(changeset) do
{:ok, room} ->
assoc_changeset = Sling.UserRoom.changeset(
%Sling.UserRoom{},
%{user_id: current_user.id, room_id: room.id}
)
Repo.insert(assoc_changeset)
conn
|> put_status(:created)
|> render("show.json", room: room)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(Sling.ChangesetView, "error.json", changeset: changeset)
end
end
def join(conn, %{"id" => room_id}) do
current_user = Guardian.Plug.current_resource(conn)
room = Repo.get(Room, room_id)
changeset = Sling.UserRoom.changeset(
%Sling.UserRoom{},
%{room_id: room.id, user_id: current_user.id}
)
case Repo.insert(changeset) do
{:ok, _user_room} ->
conn
|> put_status(:created)
|> render("show.json", %{room: room})
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(Sling.ChangesetView, "error.json", changeset: changeset)
end
end
end
@@ -3,6 +3,8 @@ defmodule Sling.UserController do
alias Sling.User
plug Guardian.Plug.EnsureAuthenticated, handler: Sling.SessionController, only: [:rooms]
def create(conn, params) do
changeset = User.registration_changeset(%User{}, params)
@@ -20,4 +22,10 @@ defmodule Sling.UserController do
|> render(Sling.ChangesetView, "error.json", changeset: changeset)
end
end
def rooms(conn, _params) do
current_user = Guardian.Plug.current_resource(conn)
rooms = Repo.all(assoc(current_user, :rooms))
render(conn, Sling.RoomView, "index.json", %{rooms: rooms})
end
end
View
@@ -0,0 +1,18 @@
defmodule Sling.Room do
use Sling.Web, :model
schema "rooms" do
field :name, :string
field :topic, :string
many_to_many :users, Sling.User, join_through: "user_rooms"
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name, :topic])
|> validate_required([:name])
|> unique_constraint(:name)
end
end
View
@@ -6,6 +6,7 @@ defmodule Sling.User do
field :email, :string
field :password_hash, :string
field :password, :string, virtual: true
many_to_many :rooms, Sling.Room, join_through: "user_rooms"
timestamps()
end
@@ -0,0 +1,17 @@
defmodule Sling.UserRoom do
use Sling.Web, :model
schema "user_rooms" do
belongs_to :user, Sling.User
belongs_to :room, Sling.Room
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:user_id, :room_id])
|> validate_required([:user_id, :room_id])
|> unique_constraint(:user_id_room_id)
end
end
View
@@ -28,5 +28,8 @@ defmodule Sling.Router do
delete "/sessions", SessionController, :delete
post "/sessions/refresh", SessionController, :refresh
resources "/users", UserController, only: [:create]
get "/users/:id/rooms", UserController, :rooms
resources "/rooms", RoomController, only: [:index, :create]
post "/rooms/:id/join", RoomController, :join
end
end
View
@@ -0,0 +1,19 @@
defmodule Sling.RoomView do
use Sling.Web, :view
def render("index.json", %{rooms: rooms}) do
%{data: render_many(rooms, Sling.RoomView, "room.json")}
end
def render("show.json", %{room: room}) do
%{data: render_one(room, Sling.RoomView, "room.json")}
end
def render("room.json", %{room: room}) do
%{
id: room.id,
name: room.name,
topic: room.topic
}
end
end

0 comments on commit 2fef1fd

Please sign in to comment.