Griffin
Model
-
JSON-like data modeling which seamlessly hooks into GraphQL
-
CRUD validation support (integrate from Vex/Ecto?)
-
Persistance agonstic with adapters
Lifecycle of CRUD operation...
defmodule WizardModel do
import Griffin.Model
@fields [
name: [:string, :required],
school: [:map, of: [
name: [:string],
geo: [:map, of: [
lat: [:int, :required],
lng: [:int, :required]
]]
]]
]
def resolve(ctx) do
ctx
|> validate(@fields)
|> denormalize_spells
|> persist
|> join_spells
|> send_weclome_email
|> to_response
end
end
View
-
Isomorphic: On the server it outputs a string; On the client it hooks into VirtualDOM/Morphdom
state() is an Agent that references a single immutable map -
Component lifecycle hooks?
-
Components + Routes > Views + Controllers?
defmodule ArtistView
use Griffin.View
defp before_mount
# jQuery thing here
end
defp styles
%{
container: %{
width: "100%"
},
header: %{
text_transform: "uppercase"
}
}
end
def render
div(:container,
h1(:header, "Artist name:"),
p(:name, state().artist.name),
button(%{ onclick: HomeController.follow_artist },
"Follow #{state().artist.name"))
end
end
Controller
defmodule HomeController
use Griffin.Controller
def follow_artist
%{ name: name } = mutate """{
follow_artist(id: #{state().artist._id}) {
name
}
}
"""
set_state %{ state() | name: name }
end
def home
%{ artists: artists } = query """{
artists(limit: 10) {
id
name
}
}
"""
set_state %{ state() | artists: artists }
render HomeView
end
end
Apps
-
Individual Plug apps
-
Provides a place for routing/glue
-
Separated by page reloads... (or not b/c enforced stateless?)
-
A root "project" combines apps to be passed into Cowboy
defmodule HomeApp do
use Griffin.App
use ArtistModel
use ArtistView
get "/", HomeController.home
end
defmodule MyProject do
use Griffin.Project
mount HomeApp
end
$ iex -S mix
iex> c "path/to/file.ex"
[MyApp]
iex> {:ok, _} = Plug.Adapters.Cowboy.http MyProject, []
{:ok, #PID<...>}