Skip to content

Instantly share code, notes, and snippets.

@mbramson
Last active May 6, 2021 00:53
Show Gist options
  • Save mbramson/77884b1532c626d2f6d7f2f64bf4f1e8 to your computer and use it in GitHub Desktop.
Save mbramson/77884b1532c626d2f6d7f2f64bf4f1e8 to your computer and use it in GitHub Desktop.
My UltiSnips Snippets
# Registers to set beforehand:
# r - resource snake_case singular (ex: 'resource')
# s - resource snake_case plural (ex: 'resources')
# v - resource CamelCase singular (ex: 'Resource')
# c - context CamelCase singular (ex: 'Resources')
# p - project name (ex: 'Pairmotron')
# <space>r on line below
# r - resource
# s - resources
# v - ResourceSchemaModule
# c - Context
# p - App
# ecto schema
# [test] context new
# [test] context basic
# view json
# view html
# router resources
# [test] controller bare
# [test] controller html
# controller fallback not found
# schema object
# factory sequence
snippet "ecto schema" "basic ecto schema" bm
defmodule ${5:`!v @p`}.${4:`!v @c`}.${3:`!v @v`} do
@moduledoc """
Ecto schema and changeset for
"""
use Ecto.Schema
use StructAccess
import Ecto.Changeset
alias __MODULE__
schema "${2:`!v @s`}" do
field(:$6, :string)
timestamps(type: :utc_datetime_usec)
end
@fields ~w($6)a
@required_fields ~w()a
def changeset(%$3{} = ${1:`!v @r`}, attrs) do
$1
|> cast(attrs, @fields)
|> validate_required(@required_fields)
|> EctoSanitizer.sanitize_all_strings()
end
end
endsnippet
snippet "context new" "shell for a brand new context" bm
defmodule ${5:`!v @p`}.${4:`!v @c`} do
@moduledoc """
Context for the $4 domain.
"""
import Ecto.Query, warn: false
alias $5.Repo
end
endsnippet
snippet "test context new" "test shell for a brand new context" bm
defmodule ${5:`!v @p`}.${4:`!v @c`}Test do
use $5.DataCase, async: true
alias $5.$4
end
endsnippet
snippet "context basic" "functions that make up a basic context" bm
alias ${5:`!v @p`}.${4:`!v @c`}.${2:`!v @v`}
def list_${1:`!v @s`} do
query = from ${3:`!v @r`} in $2,
order_by: [asc: :id]
Repo.all(query)
end
def list_$1_with_assocs do
query = from $3 in $2,
order_by: [asc: :id]
Repo.all(query)
end
def get_$3(id) do
case Repo.get($2, id) do
%$2{} = $3 ->
{:ok, $3}
_ ->
{:error, {:not_found, :$3}}
end
end
def get_$3_with_assocs(id) do
query = from ${3:`!v @r`} in $2,
where: $3.id == ^id
case Repo.one(query) do
%$2{} = $3 -> {:ok, $3}
_ -> {:error, {:not_found, :$3}}
end
end
def change_$3(%$2{} = $3 \\\\ %$2{}) do
$2.changeset($3, %{})
end
def create_$3(attrs) do
%$2{}
|> $2.changeset(attrs)
|> Repo.insert()
end
def update_$3($3, attrs) do
$3
|> $2.changeset(attrs)
|> Repo.update()
end
def delete_$3(%$2{} = $3) do
Repo.delete($3)
end
endsnippet
snippet "test context basic" "tests for basic context" bm
describe "list_${1:`!v @s`}/0" do
test "lists all $1" do
existing_${2:`!v @r`} = insert(:$2)
assert [returned_$2] = ${3:`!v @c`}.list_$1()
assert returned_$2.id == existing_$2.id
end
end
describe "list_$1_with_assocs/0" do
test "lists all $1" do
existing_$2 = insert(:$2)
assert [returned_$2] = $3.list_$1_with_assocs()
assert returned_$2.id == existing_$2.id
end
end
describe "get_$2/1" do
test "returns $2 if it exists" do
existing_$2 = insert(:$2)
assert {:ok, returned_$2} =
$3.get_$2(existing_$2.id)
assert returned_$2.id == existing_$2.id
end
test "returns error if $2 does not exist" do
assert {:error, {:not_found, :$2}} =
$3.get_$2(-1)
end
end
describe "get_$2_with_assocs/1" do
test "returns $2 if it exists" do
existing_$2 = insert(:$2)
assert {:ok, returned_$2} =
$3.get_$2_with_assocs(existing_$2.id)
assert returned_$2.id == existing_$2.id
end
test "returns error if $2 does not exist" do
assert {:error, {:not_found, :$2}} =
$3.get_$2_with_assocs(-1)
end
end
describe "change_$2/1" do
test "returns a blank changeset by default" do
assert %Ecto.Changeset{} = $3.change_$2()
end
test "accepts an existing $2" do
$2 = build(:$2)
assert %Ecto.Changeset{} = $3.change_$2($2)
end
end
describe "create_$2/1" do
test "creates $2 with valid attrs" do
attrs = params_for(:$2)
assert {:ok, $2} = $3.create_$2(attrs)
end
test "fails with invalid params" do
assert {:error, changeset} = $3.create_$2(%{})
end
end
describe "update_$2/2" do
test "updates $2 with new attrs" do
$2 = insert(:$2)
attrs = params_for(:$2)
assert {:ok, updated_$2} =
$3.update_$2($2, attrs)
Enum.each(attrs, fn {field, value} ->
assert Map.get(updated_$2, field) == value
end)
end
test "errors when given invalid attrs" do
$2 = insert(:$2)
# Snippet: Add real invalid attribute
attrs = params_for(:$2, name: "")
assert {:error, changeset} =
$3.update_$2($2, attrs)
end
end
describe "delete_$2/1" do
test "deletes a $2" do
$2 = insert(:$2)
assert {:ok, _deleted_$2} =
$3.delete_$2($2)
assert $3.get_$2($2.id) ==
{:error, {:not_found, :$2}}
end
end
endsnippet
snippet "view json" "basic phoenix json view" bm
defmodule ${5:`!v @p`}Web.${3:`!v @v`}View do
use $5Web, :view
alias $5Web.$3View
def render("index.json", %{${2:`!v @s`}: $2}) do
%{$2: render_many($2, $3View, "${1:`!v @r`}.json")}
end
def render("show.json", %{$1: $1}) do
%{$1: render_one($1, $3View, "$1.json")}
end
def render("$1.json", %{$1: $1}) do
%{
$6: $1.$6,
}
end
end
endsnippet
snippet "view html" "basic phoenix html view" bm
defmodule ${5:`!v @p`}Web.${1:`!v @v`}View do
use $5Web, :view
end
endsnippet
snippet "router resources" "router resources" bm
resources "/${2:`!v @s`}", ${3:`!v @v`}Controller
endsnippet
snippet "controller bare" "basic phoenix controller with no functions" bm
defmodule ${5:`!v @p`}Web.${3:`!v @v`}Controller do
@moduledoc """
Handles CRUD activity for $3s.
"""
use $5Web, :controller
alias $5.${4:`!v @c`}
action_fallback($5Web.FallbackController)
end
endsnippet
snippet "test controller bare" "test boilerplate for phoenix controller with no functions" bm
defmodule ${5:`!v @p`}Web.${3:`!v @v`}ControllerTest do
use $5Web.ConnCase, async: true
setup do
{conn, user} = conn_with_authenticated_user()
{:ok, conn: conn, user: user}
end
end
endsnippet
snippet "controller html" "basic phoenix html controller" bm
defmodule ${5:`!v @p`}Web.${3:`!v @v`}Controller do
@moduledoc """
Handles CRUD activity for \`$3\`s.
"""
use $5Web, :controller
alias $5.${4:`!v @c`}
action_fallback($5Web.FallbackController)
def index(conn, _params) do
${2:`!v @s`} = $4.list_$2_with_assocs()
title = "All $3s"
render(conn, "index.html", $2: $2, title: title)
end
def new(conn, _params) do
changeset = $4.change_${1:`!v @r`}()
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"$1" => $1_params}) do
case $4.create_$1($1_params) do
{:ok, $1} ->
conn
|> put_flash(:info, "$3 created successfully.")
|> redirect(to: Routes.$1_path(conn, :show, $1))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
with {:ok, $1} <- $4.get_$1_with_assocs(id) do
render(conn, "show.html", $1: $1)
end
end
def edit(conn, %{"id" => id}) do
with {:ok, $1} <- $4.get_$1(id) do
changeset = $4.change_$1($1)
render(conn, "edit.html", $1: $1, changeset: changeset)
end
end
def update(conn, %{"id" => id, "$1" => $1_params}) do
with {:ok, $1} <- $4.get_$1(id) do
case $4.update_$1($1, $1_params) do
{:ok, $1} ->
conn
|> put_flash(:info, "$3 updated successfully.")
|> redirect(to: Routes.$1_path(conn, :show, $1))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "edit.html", $1: $1, changeset: changeset)
end
end
end
def delete(conn, %{"id" => id}) do
with {:ok, $1} <- $4.get_$1(id) do
{:ok, _$1} = $4.delete_$1($1)
conn
|> put_flash(:info, "$3 deleted successfully.")
|> redirect(to: Routes.$1_path(conn, :index))
end
end
end
endsnippet
snippet "test controller html" "tests for a phoenix html controller" bm
defmodule ${5:`!v @p`}Web.${3:`!v @v`}ControllerTest do
use $5Web.ConnCase, async: true
alias $5.${4:`!v @c`}
setup do
{conn, admin_user} = conn_with_authenticated_user()
{:ok, conn: conn, admin_user: admin_user}
end
describe "index/2" do
test "renders ${2:`!v @s`}", %{conn: conn} do
insert(:${1:`!v @r`})
conn = get(conn, $1_path(conn, :index))
assert response = html_response(conn, 200)
assert response =~ "All $3s"
end
end
describe "new/2" do
test "renders the form for creating a $1", %{conn: conn} do
conn = get(conn, $1_path(conn, :new))
assert response = html_response(conn, 200)
assert response =~ "New $3"
end
end
describe "create/2" do
test "creates a $1", %{conn: conn} do
$1_params = params_for(:$1)
params = %{$1: $1_params}
conn = post(conn, $1_path(conn, :create), params)
assert %{id: id} = redirected_params(conn)
assert redirected_to(conn) == $1_path(conn, :show, id)
assert {:ok, _$1} = $4.get_$1(id)
end
test "renders errors with invalid params", %{conn: conn} do
params = %{$1: %{}}
conn = post(conn, $1_path(conn, :create), params)
assert html_response(conn, 200) =~ "New $3"
end
end
describe "show/2" do
test "renders a $1", %{conn: conn} do
$1 = insert(:$1)
conn = get(conn, $1_path(conn, :show, $1))
assert response = html_response(conn, 200)
assert response =~ "Show $3 #{$1.id}"
end
test "redirects if the $1 does not exist", %{conn: conn} do
conn = get(conn, $1_path(conn, :show, -1))
assert redirected_to(conn) == $1_path(conn, :index)
assert get_flash(conn, :error) =~ "$3 not found"
end
end
describe "edit/2" do
test "renders the form for editing an existing $1", %{conn: conn} do
$1 = insert(:$1)
conn = get(conn, $1_path(conn, :edit, $1))
assert response = html_response(conn, 200)
assert response =~ "Edit $3"
end
test "redirects with error if $1 does not exist", %{conn: conn} do
conn = get(conn, $1_path(conn, :edit, -1))
assert redirected_to(conn) == $1_path(conn, :index)
assert get_flash(conn, :error) =~ "$3 not found"
end
end
describe "update/2" do
test "updates a $1", %{conn: conn} do
$1 = insert(:$1)
$1_attrs = params_for(:$1)
params = %{$1: $1_attrs}
conn = put(conn, $1_path(conn, :update, $1.id), params)
assert redirected_to(conn) == $1_path(conn, :show, $1.id)
assert get_flash(conn, :info) =~ "$3 updated successfully."
end
test "renders errors if params are invalid", %{conn: conn} do
$1 = insert(:$1)
# Snippet: Add invalid update params here
$1_attrs = params_for(:$1, name: "")
params = %{$1: $1_attrs}
conn = put(conn, $1_path(conn, :update, $1.id), params)
assert response = html_response(conn, 200)
assert response =~ "something went wrong"
end
test "redirects with error if $1 does not exist", %{conn: conn} do
conn = put(conn, $1_path(conn, :update, -1), $1: %{})
assert redirected_to(conn) == $1_path(conn, :index)
assert get_flash(conn, :error) =~ "$3 not found"
end
end
describe "delete/2" do
test "deletes a $1", %{conn: conn} do
$1 = insert(:$1)
conn = delete(conn, $1_path(conn, :delete, $1))
assert redirected_to(conn) == $1_path(conn, :index)
assert get_flash(conn, :info) =~ "$3 deleted successfully."
end
test "redirects with error if $1 does not exist", %{conn: conn} do
conn = delete(conn, $1_path(conn, :delete, -1))
assert redirected_to(conn) == $1_path(conn, :index)
assert get_flash(conn, :error) =~ "$3 not found"
end
end
end
endsnippet
snippet "controller fallback not found" "fallback controller function head for not found resource" bm
def call(conn, {:error, {:not_found, :${1:`!v @r`}}}) do
conn
|> put_flash(:error, "${3:`!v @v`} not found")
|> redirect(to: Routes.$1_path(conn, :index))
end
endsnippet
snippet "schema object" "OpenApiSpex schema object" bm
defmodule ${5:`!v @p`}Web.Schemas.Objects.${3:`!v @v`} do
@moduledoc false
alias OpenApiSpex.Schema
require OpenApiSpex
OpenApiSpex.schema %{
type: :object,
description: "${6:Object Description}",
properties: %{
id: %Schema{type: :integer, description: "Database Identifier for this $3", example: 1},
},
required: [:id]
}
end
endsnippet
snippet "factory sequence" "ExMachina Factory field with sequence" bm
${1:field_name}: sequence(:$1, &"$1-#{&1}"),
endsnippet
# Registers to set beforehand:
# r - resource snake_case singular (ex: 'resource')
# s - resource snake_case plural (ex: 'resources')
# v - resource CamelCase singular (ex: 'Resource')
# c - context CamelCase singular (ex: 'Resources')
# p - project name (ex: 'Pairmotron')
# <space>r on line below
# r - resource
# s - resources
# v - ResourceSchemaModule
# c - Context
# p - App
# template index
# template index header
# template index value
# template index value association
# template index boolean
# template index pagination
# template show
# template show row
# template show row datetime
# template show row association
# template form
# template form text
# template form number
# template form boolean
# template form date
# template form datetime
# template form association
# template new
# template edit
snippet "template index" "index html eex template" bm
<h2>
<%= @title %>
<%= link "New ${3:`!v @v`}", to: Routes.$1_path(@conn, :new), class: "btn btn-primary ml-3 my-1" %>
</h2>
<table class="table">
<thead>
<tr>
<th>ID</th>
template index header
<th></th>
</tr>
</thead>
<tbody>
<%= for ${1:`!v @r`} <- @${2:`!v @s`} do %>
<tr>
<td><%= link $1.id, to: Routes.$1_path(@conn, :show, $1) %></td>
template index value
template index value datetime
template index value association
<td class="text-right">
<span><%= link "Show", to: Routes.$1_path(@conn, :show, $1), class: "btn btn-default btn-xs" %></span>
<span><%= link "Edit", to: Routes.$1_path(@conn, :edit, $1), class: "btn btn-default btn-xs" %></span>
<span><%= link "Delete", to: Routes.$1_path(@conn, :delete, $1), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger btn-xs" %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= link "New $3", to: Routes.$1_path(@conn, :new) %></span>
endsnippet
snippet "template index header" "table header" bm
<th>$1</th>
endsnippet
snippet "template index value" "value column in index" bm
<td><%= ${1:`!v @r`}.${2:field} %></td>
endsnippet
snippet "template index value datetime" "datetime value column in index" bm
<td><%= pretty_datetime(${1:`!v @r`}.${2:field}) %></td>
endsnippet
snippet "template index value association" "optional association value column in index" bm
<%= if ${1:`!v @r`}.${2:association} do %>
<td><%= link $1.$2.name, to: Routes.$2_path(@conn, :show, $1.$2) %></td>
<% else %>
<td>No ${3:Association}</td>
<% end %>
endsnippet
snippet "template index value boolean" "Boolean with color coding in index" bm
<%= if ${1:`v @r`}.${2:field} do %>
<td class="text-success">True</td>
<% else %>
<td class="text-danger">False</td>
<% end %>
endsnippet
snippet "template index pagination" "Pagination controls for index page" bm
<div class="d-flex justify-content-center mb-4">
<% page = page_for(@conn) %>
<% limit = limit_for(@conn) %>
<%= unless page == 1 do %>
<div class="mr-2">
<%= link "Back", to: Routes.${1:`!v @r`}_path(@conn, :index, merge_params(@conn, page: page - 1, limit: limit)) %>
</div>
<% end %>
<%= if length(@${2:`!v @s`}) == limit do %>
<div>
<%= link "Next", to: Routes.$1_path(@conn, :index, merge_params(@conn, page: page + 1, limit: limit)) %>
</div>
<% end %>
</div>
endsnippet
snippet "template show" "show html eex template" bm
<h2>
Show ${3:`!v @v`} <%= @${1:`!v @r`}.id %>
<%= link "Edit", to: Routes.$1_path(@conn, :edit, @$1), class: "btn btn-primary ml-3 my-1" %></span>
</h2>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Field</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
template show row
template show row datetime
template show row association
</tbody>
</table>
<span><%= link "Back", to: Routes.$1_path(@conn, :index) %></span>
endsnippet
snippet "template show row" "basic row on the show template" bm
<tr>
<th scope="row">
${1:Field Name}
<span phx-update="ignore" id="$3_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $3_tooltip_text() %>">
</span>
</th>
<td><%= @${2:`!v @r`}.${3:field_name} %></td>
</tr>
endsnippet
snippet "template show row datetime" "row on the show template with pretty datetime" bm
<tr>
<th scope="row">
${1:Field Name}
<span phx-update="ignore" id="$3_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $3_tooltip_text() %>">
</span>
</th>
<td><%= pretty_datetime(@${2:`!v @r`}.${3:field_name}) %></td>
</tr>
endsnippet
snippet "template show row association" "row on the show template that links" bm
<tr>
<th scope="row">
${1:Field Name}
<span phx-update="ignore" id="$3_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $3_tooltip_text() %>">
</span>
</th>
<%= if @${2:`!v @r`}.${3:association_field_name} do %>
<td><%= link @$2.$3.name, to: Routes.$3_path(@conn, :show, @$2.$3) %></td>
<% else %>
<td>(None)</td>
<% end %>
</tr>
endsnippet
snippet "template form" "form html eex template" bm
<%= form_for @changeset, @action, fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
template form text
template form number
template form boolean
template form date
template form datetime
template form association
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
endsnippet
snippet "template form text" "field on template form for text input" bm
<div class="form-group">
<%= label f, :${1:field_name}, class: "control-label" %>
<span phx-update="ignore" id="$1_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $1_tooltip_text() %>">
</span>
<%= inline_error_tag f, :$1 %>
<%= text_input f, :$1, class: "form-control" %>
</div>
endsnippet
snippet "template form number" "field on template form for number input" bm
<div class="form-group">
<%= label f, :${1:field_name}, class: "control-label" %>
<span phx-update="ignore" id="$1_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $1_tooltip_text() %>">
</span>
<%= inline_error_tag f, :$1 %>
<%= number_input f, :$1, class: "form-control" %>
</div>
endsnippet
snippet "template form boolean" "field on template form for booleans" bm
<div class="form-group">
<%= label f, :${1:field_name}, class: "control-label" %>
<span phx-update="ignore" id="$1_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $1_tooltip_text() %>">
</span>
<%= inline_error_tag f, :$1 %>
<%= select f, :$1, boolean_select(false), class: "form-control" %>
</div>
endsnippet
snippet "template form date" "field on template form for dates" bm
<div class="form-group">
<%= label f, :${1:field_name}, class: "control-label" %>
<span phx-update="ignore" id="$1_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $1_tooltip_text() %>">
</span>
<%= inline_error_tag f, :$1 %>
<%= date_select f, :$1, class: "form-control" %>
</div>
endsnippet
snippet "template form datetime" "field on template form for dates" bm
<div class="form-group">
<%= label f, :${1:field_name}, class: "control-label" %>
<span phx-update="ignore" id="$1_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $1_tooltip_text() %>">
</span>
<%= inline_error_tag f, :$1 %>
<%= datetime_select f, :$1, year: [options: 1900..2019], class: "form-control" %>
</div>
endsnippet
snippet "template form association" "field on template form for selecting associations" bm
<div class="form-group">
<%= label f, :${1:association_field_name}_id, "${2:AssociationFieldName}", class: "control-label" %>
<span phx-update="ignore" id="$1_tooltip_container">
<img src="<%= Routes.static_path(@conn, "/images/question_circle.svg") %>"
data-toggle="tooltip"
data-html="true"
title="<%= $1_tooltip_text() %>">
</span>
<%= inline_error_tag f, :$1_id %>
<%= inline_error_tag f, :$1 %>
<%= select f, :$1_id, data_as_select(@${3:association_plural}), prompt: "(none)", class: "form-control" %>
</div>
endsnippet
snippet "template new" "new html eex template" bm
<h2>New ${1:`!v @v`}</h2>
<%= render "form.html", Map.put(assigns, :action, Routes.${2:`!v @r`}_path(@conn, :create)) %>
<span><%= link "Back", to: Routes.$2_path(@conn, :index) %></span>
endsnippet
snippet "template edit" "edit html eex template" bm
<h2>Edit ${1:`!v @v`}</h2>
<%= render "form.html", Map.put(assigns, :action, Routes.${2:`!v @r`}_path(@conn, :update, @$2)) %>
<span><%= link "Back", to: Routes.$2_path(@conn, :index) %></span>
endsnippet
" for populating registers in UltiSnips
nnoremap <space>r _www"ryiwj"syiwj"vyiwj"cyiwj"pyiw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment