Last active
June 12, 2016 05:39
-
-
Save gogogarrett/fa578e808d47bec79e3aaa2f64428dbd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# phoenix controller | |
defmodule ExWeb.Api.V3.ArcadeController do | |
use ExWeb.Web, :controller | |
alias ExWeb.{Repo, ArcadeGame, Student} | |
# delegating entire lobic out into a sub app/package (otp or not..) | |
# Here I am trying to make the `PlayArcadeGame` super generic and _not_ coupled to phoenix. | |
# I am trying to pass in all the required info needed up front.. but idk how this will scale | |
# with more complex business things. | |
def play_game(conn, %{"game" => %{"id" => id}}) do | |
case PlayArcadeGame.call(Repo, {Student, current_user}, fetch_game(id)) do | |
{:ok, _msg} -> | |
conn |> send_resp(201, "") | |
{:error, reason} -> | |
conn |> send_resp(422, reason) | |
end | |
end | |
# stubs below | |
defp current_user do | |
Repo.get(Student, 1) | |
end | |
defp fetch_game(id) do | |
Repo.one(from(ac in ArcadeGame, where: ac.name == ^id)) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# main business logic | |
# trying to be decoupled from reaching outside of it's context | |
defmodule PlayArcadeGame do | |
def call(repo, {student_struct, student_model}, game) | |
steps(repo, {student_struct, student_model}, game) | |
|> Workflow.call(repo) | |
end | |
defp steps(repo, {student_struct, student_model} = student_info, game) do | |
fn -> | |
with {:ok, _} <- Service.EnsureEnoughAcorns.call(student.acorns, game.cost), | |
{:ok, _} <- Service.AwardAcorns.call(repo, student_info, -game.cost), | |
{:ok, _} <- Service.CreateStudentEvent.call(%{id: 1}), | |
do: {:ok, "workflow successful"} | |
end | |
end | |
end | |
# single steps / services of the logic | |
defmodule Service.EnsureEnoughAcorns do | |
def call(acorns, cost) when acorns >= cost do | |
{:ok, ""} | |
end | |
def call(_acorns, _cost) do | |
{:error, "not enough acorns"} | |
end | |
end | |
defmodule Service.CreateStudentEvent do | |
def call(map) do | |
case create_student_event(map) do | |
_event -> | |
{:ok, "event created."} | |
_ -> | |
{:error, "event could not be created."} | |
end | |
end | |
defp create_student_event(map) do | |
# ie. | |
# %{ | |
# student_id: student.id, | |
# precinct: 'arcade', | |
# event_type: 'ArcadeGame' | |
# } | |
# BlakeProgress.Service.create_student_event(map) | |
%{id: 1} | |
end | |
end | |
defmodule Service.AwardAcorns do | |
def call(repo, {student_struct, student_model}, amount \\ 3) do | |
student_model | |
|> student_struct.changeset(%{acorns: student_model.acorns + amount}) | |
|> repo.update() | |
end | |
end | |
# another common package possibly | |
# simply to wrap things in a transaction and rollback if all fails | |
defmodule Workflow do | |
def call(function, repo) do | |
repo.transaction fn() -> | |
case function.() do | |
{:ok, result} -> result | |
{:error, error} -> repo.rollback(error) | |
end | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment