feat: Generate end-developer app
This commit is contained in:
parent
96f6566c28
commit
e5773dbbcf
114 changed files with 11564 additions and 1 deletions
4
apps/app/.formatter.exs
Normal file
4
apps/app/.formatter.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
import_deps: [:phoenix],
|
||||
inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
34
apps/app/.gitignore
vendored
Normal file
34
apps/app/.gitignore
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where 3rd-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
app-*.tar
|
||||
|
||||
# If NPM crashes, it generates a log, let's ignore it too.
|
||||
npm-debug.log
|
||||
|
||||
# The directory NPM downloads your dependencies sources to.
|
||||
/assets/node_modules/
|
||||
|
||||
# Since we are building assets from assets/,
|
||||
# we ignore priv/static. You may want to comment
|
||||
# this depending on your deployment strategy.
|
||||
/priv/static/
|
20
apps/app/README.md
Normal file
20
apps/app/README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# App
|
||||
|
||||
To start your Phoenix server:
|
||||
|
||||
* Install dependencies with `mix deps.get`
|
||||
* Create and migrate your database with `mix ecto.setup`
|
||||
* Install Node.js dependencies with `npm install` inside the `assets` directory
|
||||
* Start Phoenix endpoint with `mix phx.server`
|
||||
|
||||
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
|
||||
|
||||
Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
|
||||
|
||||
## Learn more
|
||||
|
||||
* Official website: https://www.phoenixframework.org/
|
||||
* Guides: https://hexdocs.pm/phoenix/overview.html
|
||||
* Docs: https://hexdocs.pm/phoenix
|
||||
* Forum: https://elixirforum.com/c/phoenix-forum
|
||||
* Source: https://github.com/phoenixframework/phoenix
|
5
apps/app/assets/.babelrc
Normal file
5
apps/app/assets/.babelrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
]
|
||||
}
|
31
apps/app/assets/css/app.scss
Normal file
31
apps/app/assets/css/app.scss
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* This file is for your main application css. */
|
||||
@import "./phoenix.css";
|
||||
|
||||
/* Alerts and form errors */
|
||||
.alert {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.alert-info {
|
||||
color: #31708f;
|
||||
background-color: #d9edf7;
|
||||
border-color: #bce8f1;
|
||||
}
|
||||
.alert-warning {
|
||||
color: #8a6d3b;
|
||||
background-color: #fcf8e3;
|
||||
border-color: #faebcc;
|
||||
}
|
||||
.alert-danger {
|
||||
color: #a94442;
|
||||
background-color: #f2dede;
|
||||
border-color: #ebccd1;
|
||||
}
|
||||
.alert p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.alert:empty {
|
||||
display: none;
|
||||
}
|
101
apps/app/assets/css/phoenix.css
Normal file
101
apps/app/assets/css/phoenix.css
Normal file
File diff suppressed because one or more lines are too long
15
apps/app/assets/js/app.js
Normal file
15
apps/app/assets/js/app.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
// We need to import the CSS so that webpack will load it.
|
||||
// The MiniCssExtractPlugin is used to separate it out into
|
||||
// its own CSS file.
|
||||
import "../css/app.scss"
|
||||
|
||||
// webpack automatically bundles all modules in your
|
||||
// entry points. Those entry points can be configured
|
||||
// in "webpack.config.js".
|
||||
//
|
||||
// Import deps with the dep name or local files with a relative path, for example:
|
||||
//
|
||||
// import {Socket} from "phoenix"
|
||||
// import socket from "./socket"
|
||||
//
|
||||
import "phoenix_html"
|
63
apps/app/assets/js/socket.js
Normal file
63
apps/app/assets/js/socket.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
// NOTE: The contents of this file will only be executed if
|
||||
// you uncomment its entry in "assets/js/app.js".
|
||||
|
||||
// To use Phoenix channels, the first step is to import Socket,
|
||||
// and connect at the socket path in "lib/web/endpoint.ex".
|
||||
//
|
||||
// Pass the token on params as below. Or remove it
|
||||
// from the params if you are not using authentication.
|
||||
import {Socket} from "phoenix"
|
||||
|
||||
let socket = new Socket("/socket", {params: {token: window.userToken}})
|
||||
|
||||
// When you connect, you'll often need to authenticate the client.
|
||||
// For example, imagine you have an authentication plug, `MyAuth`,
|
||||
// which authenticates the session and assigns a `:current_user`.
|
||||
// If the current user exists you can assign the user's token in
|
||||
// the connection for use in the layout.
|
||||
//
|
||||
// In your "lib/web/router.ex":
|
||||
//
|
||||
// pipeline :browser do
|
||||
// ...
|
||||
// plug MyAuth
|
||||
// plug :put_user_token
|
||||
// end
|
||||
//
|
||||
// defp put_user_token(conn, _) do
|
||||
// if current_user = conn.assigns[:current_user] do
|
||||
// token = Phoenix.Token.sign(conn, "user socket", current_user.id)
|
||||
// assign(conn, :user_token, token)
|
||||
// else
|
||||
// conn
|
||||
// end
|
||||
// end
|
||||
//
|
||||
// Now you need to pass this token to JavaScript. You can do so
|
||||
// inside a script tag in "lib/web/templates/layout/app.html.eex":
|
||||
//
|
||||
// <script>window.userToken = "<%= assigns[:user_token] %>";</script>
|
||||
//
|
||||
// You will need to verify the user token in the "connect/3" function
|
||||
// in "lib/web/channels/user_socket.ex":
|
||||
//
|
||||
// def connect(%{"token" => token}, socket, _connect_info) do
|
||||
// # max_age: 1209600 is equivalent to two weeks in seconds
|
||||
// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
|
||||
// {:ok, user_id} ->
|
||||
// {:ok, assign(socket, :user, user_id)}
|
||||
// {:error, reason} ->
|
||||
// :error
|
||||
// end
|
||||
// end
|
||||
//
|
||||
// Finally, connect to the socket:
|
||||
socket.connect()
|
||||
|
||||
// Now that you are connected, you can join channels with a topic:
|
||||
let channel = socket.channel("topic:subtopic", {})
|
||||
channel.join()
|
||||
.receive("ok", resp => { console.log("Joined successfully", resp) })
|
||||
.receive("error", resp => { console.log("Unable to join", resp) })
|
||||
|
||||
export default socket
|
7929
apps/app/assets/package-lock.json
generated
Normal file
7929
apps/app/assets/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
27
apps/app/assets/package.json
Normal file
27
apps/app/assets/package.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"repository": {},
|
||||
"description": " ",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"deploy": "webpack --mode production",
|
||||
"watch": "webpack --mode development --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"phoenix": "file:../../../deps/phoenix",
|
||||
"phoenix_html": "file:../../../deps/phoenix_html"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"babel-loader": "^8.0.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^3.4.2",
|
||||
"sass-loader": "^8.0.2",
|
||||
"node-sass": "^4.13.1",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"terser-webpack-plugin": "^2.3.2",
|
||||
"webpack": "4.41.5",
|
||||
"webpack-cli": "^3.3.2"
|
||||
}
|
||||
}
|
BIN
apps/app/assets/static/favicon.ico
Normal file
BIN
apps/app/assets/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
apps/app/assets/static/images/phoenix.png
Normal file
BIN
apps/app/assets/static/images/phoenix.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
5
apps/app/assets/static/robots.txt
Normal file
5
apps/app/assets/static/robots.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
|
||||
#
|
||||
# To ban all spiders from the entire site uncomment the next two lines:
|
||||
# User-agent: *
|
||||
# Disallow: /
|
51
apps/app/assets/webpack.config.js
Normal file
51
apps/app/assets/webpack.config.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
const path = require('path');
|
||||
const glob = require('glob');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
module.exports = (env, options) => {
|
||||
const devMode = options.mode !== 'production';
|
||||
|
||||
return {
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),
|
||||
new OptimizeCSSAssetsPlugin({})
|
||||
]
|
||||
},
|
||||
entry: {
|
||||
'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: path.resolve(__dirname, '../priv/static/js'),
|
||||
publicPath: '/js/'
|
||||
},
|
||||
devtool: devMode ? 'source-map' : undefined,
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.[s]?css$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
|
||||
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
|
||||
]
|
||||
}
|
||||
};
|
81
apps/app/lib/app.ex
Normal file
81
apps/app/lib/app.ex
Normal file
|
@ -0,0 +1,81 @@
|
|||
defmodule App do
|
||||
@moduledoc """
|
||||
The entrypoint for defining your web interface, such
|
||||
as controllers, views, channels and so on.
|
||||
|
||||
This can be used in your application as:
|
||||
|
||||
use App, :controller
|
||||
use App, :view
|
||||
|
||||
The definitions below will be executed for every view,
|
||||
controller, etc, so keep them short and clean, focused
|
||||
on imports, uses and aliases.
|
||||
|
||||
Do NOT define functions inside the quoted expressions
|
||||
below. Instead, define any helper function in modules
|
||||
and import those modules here.
|
||||
"""
|
||||
|
||||
def controller do
|
||||
quote do
|
||||
use Phoenix.Controller, namespace: App
|
||||
|
||||
import Plug.Conn
|
||||
import App.Gettext
|
||||
alias App.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
def view do
|
||||
quote do
|
||||
use Phoenix.View,
|
||||
root: "lib/app/templates",
|
||||
namespace: App
|
||||
|
||||
# Import convenience functions from controllers
|
||||
import Phoenix.Controller,
|
||||
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
|
||||
|
||||
# Include shared imports and aliases for views
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def router do
|
||||
quote do
|
||||
use Phoenix.Router
|
||||
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller
|
||||
end
|
||||
end
|
||||
|
||||
def channel do
|
||||
quote do
|
||||
use Phoenix.Channel
|
||||
import App.Gettext
|
||||
end
|
||||
end
|
||||
|
||||
defp view_helpers do
|
||||
quote do
|
||||
# Use all HTML functionality (forms, tags, etc)
|
||||
use Phoenix.HTML
|
||||
|
||||
# Import basic rendering functionality (render, render_layout, etc)
|
||||
import Phoenix.View
|
||||
|
||||
import App.ErrorHelpers
|
||||
import App.Gettext
|
||||
alias App.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
When used, dispatch to the appropriate controller/view/etc.
|
||||
"""
|
||||
defmacro __using__(which) when is_atom(which) do
|
||||
apply(__MODULE__, which, [])
|
||||
end
|
||||
end
|
31
apps/app/lib/app/application.ex
Normal file
31
apps/app/lib/app/application.ex
Normal file
|
@ -0,0 +1,31 @@
|
|||
defmodule App.Application do
|
||||
# See https://hexdocs.pm/elixir/Application.html
|
||||
# for more information on OTP Applications
|
||||
@moduledoc false
|
||||
|
||||
use Application
|
||||
|
||||
def start(_type, _args) do
|
||||
children = [
|
||||
App.Repo,
|
||||
# Start the Telemetry supervisor
|
||||
App.Telemetry,
|
||||
# Start the Endpoint (http/https)
|
||||
App.Endpoint
|
||||
# Start a worker by calling: App.Worker.start_link(arg)
|
||||
# {App.Worker, arg}
|
||||
]
|
||||
|
||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||
# for other strategies and supported options
|
||||
opts = [strategy: :one_for_one, name: App.Supervisor]
|
||||
Supervisor.start_link(children, opts)
|
||||
end
|
||||
|
||||
# Tell Phoenix to update the endpoint configuration
|
||||
# whenever the application is updated.
|
||||
def config_change(changed, _new, removed) do
|
||||
App.Endpoint.config_change(changed, removed)
|
||||
:ok
|
||||
end
|
||||
end
|
35
apps/app/lib/app/channels/user_socket.ex
Normal file
35
apps/app/lib/app/channels/user_socket.ex
Normal file
|
@ -0,0 +1,35 @@
|
|||
defmodule App.UserSocket do
|
||||
use Phoenix.Socket
|
||||
|
||||
## Channels
|
||||
# channel "room:*", App.RoomChannel
|
||||
|
||||
# Socket params are passed from the client and can
|
||||
# be used to verify and authenticate a user. After
|
||||
# verification, you can put default assigns into
|
||||
# the socket that will be set for all channels, ie
|
||||
#
|
||||
# {:ok, assign(socket, :user_id, verified_user_id)}
|
||||
#
|
||||
# To deny connection, return `:error`.
|
||||
#
|
||||
# See `Phoenix.Token` documentation for examples in
|
||||
# performing token verification on connect.
|
||||
@impl true
|
||||
def connect(_params, socket, _connect_info) do
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
# Socket id's are topics that allow you to identify all sockets for a given user:
|
||||
#
|
||||
# def id(socket), do: "user_socket:#{socket.assigns.user_id}"
|
||||
#
|
||||
# Would allow you to broadcast a "disconnect" event and terminate
|
||||
# all active sockets and channels for a given user:
|
||||
#
|
||||
# App.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
|
||||
#
|
||||
# Returning `nil` makes this socket anonymous.
|
||||
@impl true
|
||||
def id(_socket), do: nil
|
||||
end
|
7
apps/app/lib/app/controllers/page_controller.ex
Normal file
7
apps/app/lib/app/controllers/page_controller.ex
Normal file
|
@ -0,0 +1,7 @@
|
|||
defmodule App.PageController do
|
||||
use App, :controller
|
||||
|
||||
def index(conn, _params) do
|
||||
render(conn, "index.html")
|
||||
end
|
||||
end
|
54
apps/app/lib/app/endpoint.ex
Normal file
54
apps/app/lib/app/endpoint.ex
Normal file
|
@ -0,0 +1,54 @@
|
|||
defmodule App.Endpoint do
|
||||
use Phoenix.Endpoint, otp_app: :app
|
||||
|
||||
# The session will be stored in the cookie and signed,
|
||||
# this means its contents can be read but not tampered with.
|
||||
# Set :encryption_salt if you would also like to encrypt it.
|
||||
@session_options [
|
||||
store: :cookie,
|
||||
key: "_app_key",
|
||||
signing_salt: "VQMRz57g"
|
||||
]
|
||||
|
||||
socket "/socket", App.UserSocket,
|
||||
websocket: true,
|
||||
longpoll: false
|
||||
|
||||
socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
|
||||
|
||||
# Serve at "/" the static files from "priv/static" directory.
|
||||
#
|
||||
# You should set gzip to true if you are running phx.digest
|
||||
# when deploying your static files in production.
|
||||
plug Plug.Static,
|
||||
at: "/",
|
||||
from: :app,
|
||||
gzip: false,
|
||||
only: ~w(css fonts images js favicon.ico robots.txt)
|
||||
|
||||
# Code reloading can be explicitly enabled under the
|
||||
# :code_reloader configuration of your endpoint.
|
||||
if code_reloading? do
|
||||
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
|
||||
plug Phoenix.LiveReloader
|
||||
plug Phoenix.CodeReloader
|
||||
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :app
|
||||
end
|
||||
|
||||
plug Phoenix.LiveDashboard.RequestLogger,
|
||||
param_key: "request_logger",
|
||||
cookie_key: "request_logger"
|
||||
|
||||
plug Plug.RequestId
|
||||
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
|
||||
|
||||
plug Plug.Parsers,
|
||||
parsers: [:urlencoded, :multipart, :json],
|
||||
pass: ["*/*"],
|
||||
json_decoder: Phoenix.json_library()
|
||||
|
||||
plug Plug.MethodOverride
|
||||
plug Plug.Head
|
||||
plug Plug.Session, @session_options
|
||||
plug App.Router
|
||||
end
|
24
apps/app/lib/app/gettext.ex
Normal file
24
apps/app/lib/app/gettext.ex
Normal file
|
@ -0,0 +1,24 @@
|
|||
defmodule App.Gettext do
|
||||
@moduledoc """
|
||||
A module providing Internationalization with a gettext-based API.
|
||||
|
||||
By using [Gettext](https://hexdocs.pm/gettext),
|
||||
your module gains a set of macros for translations, for example:
|
||||
|
||||
import App.Gettext
|
||||
|
||||
# Simple translation
|
||||
gettext("Here is the string to translate")
|
||||
|
||||
# Plural translation
|
||||
ngettext("Here is the string to translate",
|
||||
"Here are the strings to translate",
|
||||
3)
|
||||
|
||||
# Domain-based translation
|
||||
dgettext("errors", "Here is the error message to translate")
|
||||
|
||||
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
|
||||
"""
|
||||
use Gettext, otp_app: :app
|
||||
end
|
5
apps/app/lib/app/repo.ex
Normal file
5
apps/app/lib/app/repo.ex
Normal file
|
@ -0,0 +1,5 @@
|
|||
defmodule App.Repo do
|
||||
use Ecto.Repo,
|
||||
otp_app: :app,
|
||||
adapter: Ecto.Adapters.Postgres
|
||||
end
|
42
apps/app/lib/app/router.ex
Normal file
42
apps/app/lib/app/router.ex
Normal file
|
@ -0,0 +1,42 @@
|
|||
defmodule App.Router do
|
||||
use App, :router
|
||||
|
||||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
plug :fetch_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
end
|
||||
|
||||
scope "/", App do
|
||||
pipe_through :browser
|
||||
|
||||
get "/", PageController, :index
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
# scope "/api", App do
|
||||
# pipe_through :api
|
||||
# end
|
||||
|
||||
# Enables LiveDashboard only for development
|
||||
#
|
||||
# If you want to use the LiveDashboard in production, you should put
|
||||
# it behind authentication and allow only admins to access it.
|
||||
# If your application does not have an admins-only section yet,
|
||||
# you can use Plug.BasicAuth to set up some basic authentication
|
||||
# as long as you are also using SSL (which you should anyway).
|
||||
if Mix.env() in [:dev, :test] do
|
||||
import Phoenix.LiveDashboard.Router
|
||||
|
||||
scope "/" do
|
||||
pipe_through :browser
|
||||
live_dashboard "/dashboard", metrics: App.Telemetry
|
||||
end
|
||||
end
|
||||
end
|
55
apps/app/lib/app/telemetry.ex
Normal file
55
apps/app/lib/app/telemetry.ex
Normal file
|
@ -0,0 +1,55 @@
|
|||
defmodule App.Telemetry do
|
||||
use Supervisor
|
||||
import Telemetry.Metrics
|
||||
|
||||
def start_link(arg) do
|
||||
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(_arg) do
|
||||
children = [
|
||||
# Telemetry poller will execute the given period measurements
|
||||
# every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
|
||||
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
|
||||
# Add reporters as children of your supervision tree.
|
||||
# {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}
|
||||
]
|
||||
|
||||
Supervisor.init(children, strategy: :one_for_one)
|
||||
end
|
||||
|
||||
def metrics do
|
||||
[
|
||||
# Phoenix Metrics
|
||||
summary("phoenix.endpoint.stop.duration",
|
||||
unit: {:native, :millisecond}
|
||||
),
|
||||
summary("phoenix.router_dispatch.stop.duration",
|
||||
tags: [:route],
|
||||
unit: {:native, :millisecond}
|
||||
),
|
||||
|
||||
# Database Metrics
|
||||
summary("app.repo.query.total_time", unit: {:native, :millisecond}),
|
||||
summary("app.repo.query.decode_time", unit: {:native, :millisecond}),
|
||||
summary("app.repo.query.query_time", unit: {:native, :millisecond}),
|
||||
summary("app.repo.query.queue_time", unit: {:native, :millisecond}),
|
||||
summary("app.repo.query.idle_time", unit: {:native, :millisecond}),
|
||||
|
||||
# VM Metrics
|
||||
summary("vm.memory.total", unit: {:byte, :kilobyte}),
|
||||
summary("vm.total_run_queue_lengths.total"),
|
||||
summary("vm.total_run_queue_lengths.cpu"),
|
||||
summary("vm.total_run_queue_lengths.io")
|
||||
]
|
||||
end
|
||||
|
||||
defp periodic_measurements do
|
||||
[
|
||||
# A module, function and arguments to be invoked periodically.
|
||||
# This function must call :telemetry.execute/3 and a metric must be added above.
|
||||
# {App, :count_users, []}
|
||||
]
|
||||
end
|
||||
end
|
33
apps/app/lib/app/templates/layout/app.html.eex
Normal file
33
apps/app/lib/app/templates/layout/app.html.eex
Normal file
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>App · Phoenix Framework</title>
|
||||
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<script defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<section class="container">
|
||||
<nav role="navigation">
|
||||
<ul>
|
||||
<li><a href="https://hexdocs.pm/phoenix/overview.html">Get Started</a></li>
|
||||
<%= if function_exported?(Routes, :live_dashboard_path, 2) do %>
|
||||
<li><%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</nav>
|
||||
<a href="https://phoenixframework.org/" class="phx-logo">
|
||||
<img src="<%= Routes.static_path(@conn, "/images/phoenix.png") %>" alt="Phoenix Framework Logo"/>
|
||||
</a>
|
||||
</section>
|
||||
</header>
|
||||
<main role="main" class="container">
|
||||
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
|
||||
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
|
||||
<%= @inner_content %>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
38
apps/app/lib/app/templates/page/index.html.eex
Normal file
38
apps/app/lib/app/templates/page/index.html.eex
Normal file
|
@ -0,0 +1,38 @@
|
|||
<section class="phx-hero">
|
||||
<h1><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h1>
|
||||
<p>Peace-of-mind from prototype to production</p>
|
||||
</section>
|
||||
|
||||
<section class="row">
|
||||
<article class="column">
|
||||
<h2>Resources</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://hexdocs.pm/phoenix/overview.html">Guides & Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/phoenixframework/phoenix">Source</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/phoenixframework/phoenix/blob/v1.5/CHANGELOG.md">v1.5 Changelog</a>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
<article class="column">
|
||||
<h2>Help</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://elixirforum.com/c/phoenix-forum">Forum</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://webchat.freenode.net/?channels=elixir-lang">#elixir-lang on Freenode IRC</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/elixirphoenix">Twitter @elixirphoenix</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://elixir-slackin.herokuapp.com/">Elixir on Slack</a>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
</section>
|
47
apps/app/lib/app/views/error_helpers.ex
Normal file
47
apps/app/lib/app/views/error_helpers.ex
Normal file
|
@ -0,0 +1,47 @@
|
|||
defmodule App.ErrorHelpers do
|
||||
@moduledoc """
|
||||
Conveniences for translating and building error messages.
|
||||
"""
|
||||
|
||||
use Phoenix.HTML
|
||||
|
||||
@doc """
|
||||
Generates tag for inlined form input errors.
|
||||
"""
|
||||
def error_tag(form, field) do
|
||||
Enum.map(Keyword.get_values(form.errors, field), fn error ->
|
||||
content_tag(:span, translate_error(error),
|
||||
class: "invalid-feedback",
|
||||
phx_feedback_for: input_id(form, field)
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Translates an error message using gettext.
|
||||
"""
|
||||
def translate_error({msg, opts}) do
|
||||
# When using gettext, we typically pass the strings we want
|
||||
# to translate as a static argument:
|
||||
#
|
||||
# # Translate "is invalid" in the "errors" domain
|
||||
# dgettext("errors", "is invalid")
|
||||
#
|
||||
# # Translate the number of files with plural rules
|
||||
# dngettext("errors", "1 file", "%{count} files", count)
|
||||
#
|
||||
# Because the error messages we show in our forms and APIs
|
||||
# are defined inside Ecto, we need to translate them dynamically.
|
||||
# This requires us to call the Gettext module passing our gettext
|
||||
# backend as first argument.
|
||||
#
|
||||
# Note we use the "errors" domain, which means translations
|
||||
# should be written to the errors.po file. The :count option is
|
||||
# set by Ecto and indicates we should also apply plural rules.
|
||||
if count = opts[:count] do
|
||||
Gettext.dngettext(App.Gettext, "errors", msg, msg, count, opts)
|
||||
else
|
||||
Gettext.dgettext(App.Gettext, "errors", msg, opts)
|
||||
end
|
||||
end
|
||||
end
|
16
apps/app/lib/app/views/error_view.ex
Normal file
16
apps/app/lib/app/views/error_view.ex
Normal file
|
@ -0,0 +1,16 @@
|
|||
defmodule App.ErrorView do
|
||||
use App, :view
|
||||
|
||||
# If you want to customize a particular status code
|
||||
# for a certain format, you may uncomment below.
|
||||
# def render("500.html", _assigns) do
|
||||
# "Internal Server Error"
|
||||
# end
|
||||
|
||||
# By default, Phoenix returns the status message from
|
||||
# the template name. For example, "404.html" becomes
|
||||
# "Not Found".
|
||||
def template_not_found(template, _assigns) do
|
||||
Phoenix.Controller.status_message_from_template(template)
|
||||
end
|
||||
end
|
3
apps/app/lib/app/views/layout_view.ex
Normal file
3
apps/app/lib/app/views/layout_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule App.LayoutView do
|
||||
use App, :view
|
||||
end
|
3
apps/app/lib/app/views/page_view.ex
Normal file
3
apps/app/lib/app/views/page_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule App.PageView do
|
||||
use App, :view
|
||||
end
|
64
apps/app/mix.exs
Normal file
64
apps/app/mix.exs
Normal file
|
@ -0,0 +1,64 @@
|
|||
defmodule App.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :app,
|
||||
version: "0.1.0",
|
||||
build_path: "../../_build",
|
||||
config_path: "../../config/config.exs",
|
||||
deps_path: "../../deps",
|
||||
lockfile: "../../mix.lock",
|
||||
elixir: "~> 1.7",
|
||||
elixirc_paths: elixirc_paths(Mix.env()),
|
||||
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||
start_permanent: Mix.env() == :prod,
|
||||
aliases: aliases(),
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Configuration for the OTP application.
|
||||
#
|
||||
# Type `mix help compile.app` for more information.
|
||||
def application do
|
||||
[
|
||||
mod: {App.Application, []},
|
||||
extra_applications: [:logger, :runtime_tools]
|
||||
]
|
||||
end
|
||||
|
||||
# Specifies which paths to compile per environment.
|
||||
defp elixirc_paths(:test), do: ["lib", "test/support"]
|
||||
defp elixirc_paths(_), do: ["lib"]
|
||||
|
||||
# Specifies your project dependencies.
|
||||
#
|
||||
# Type `mix help deps` for examples and options.
|
||||
defp deps do
|
||||
[
|
||||
{:ecto_sql, "~> 3.4"},
|
||||
{:phoenix, "~> 1.5.3"},
|
||||
{:phoenix_ecto, "~> 4.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:postgrex, ">= 0.0.0"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
{:telemetry_poller, "~> 0.4"},
|
||||
{:gettext, "~> 0.11"},
|
||||
{:jason, "~> 1.0"},
|
||||
{:plug_cowboy, "~> 2.0"}
|
||||
]
|
||||
end
|
||||
|
||||
# Aliases are shortcuts or tasks specific to the current project.
|
||||
#
|
||||
# See the documentation for `Mix` for more info on aliases.
|
||||
defp aliases do
|
||||
[
|
||||
setup: ["deps.get", "cmd npm install --prefix assets"],
|
||||
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"]
|
||||
]
|
||||
end
|
||||
end
|
97
apps/app/priv/gettext/en/LC_MESSAGES/errors.po
Normal file
97
apps/app/priv/gettext/en/LC_MESSAGES/errors.po
Normal file
|
@ -0,0 +1,97 @@
|
|||
## `msgid`s in this file come from POT (.pot) files.
|
||||
##
|
||||
## Do not add, change, or remove `msgid`s manually here as
|
||||
## they're tied to the ones in the corresponding POT file
|
||||
## (with the same domain).
|
||||
##
|
||||
## Use `mix gettext.extract --merge` or `mix gettext.merge`
|
||||
## to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en\n"
|
||||
|
||||
## From Ecto.Changeset.cast/4
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.unique_constraint/3
|
||||
msgid "has already been taken"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.put_change/3
|
||||
msgid "is invalid"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_acceptance/3
|
||||
msgid "must be accepted"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_format/3
|
||||
msgid "has invalid format"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_subset/3
|
||||
msgid "has an invalid entry"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_exclusion/3
|
||||
msgid "is reserved"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_confirmation/3
|
||||
msgid "does not match confirmation"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.no_assoc_constraint/3
|
||||
msgid "is still associated with this entry"
|
||||
msgstr ""
|
||||
|
||||
msgid "are still associated with this entry"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_length/3
|
||||
msgid "should be %{count} character(s)"
|
||||
msgid_plural "should be %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should have %{count} item(s)"
|
||||
msgid_plural "should have %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should be at least %{count} character(s)"
|
||||
msgid_plural "should be at least %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should have at least %{count} item(s)"
|
||||
msgid_plural "should have at least %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should be at most %{count} character(s)"
|
||||
msgid_plural "should be at most %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should have at most %{count} item(s)"
|
||||
msgid_plural "should have at most %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
## From Ecto.Changeset.validate_number/3
|
||||
msgid "must be less than %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be greater than %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be less than or equal to %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be greater than or equal to %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be equal to %{number}"
|
||||
msgstr ""
|
95
apps/app/priv/gettext/errors.pot
Normal file
95
apps/app/priv/gettext/errors.pot
Normal file
|
@ -0,0 +1,95 @@
|
|||
## This is a PO Template file.
|
||||
##
|
||||
## `msgid`s here are often extracted from source code.
|
||||
## Add new translations manually only if they're dynamic
|
||||
## translations that can't be statically extracted.
|
||||
##
|
||||
## Run `mix gettext.extract` to bring this file up to
|
||||
## date. Leave `msgstr`s empty as changing them here has no
|
||||
## effect: edit them in PO (`.po`) files instead.
|
||||
|
||||
## From Ecto.Changeset.cast/4
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.unique_constraint/3
|
||||
msgid "has already been taken"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.put_change/3
|
||||
msgid "is invalid"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_acceptance/3
|
||||
msgid "must be accepted"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_format/3
|
||||
msgid "has invalid format"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_subset/3
|
||||
msgid "has an invalid entry"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_exclusion/3
|
||||
msgid "is reserved"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_confirmation/3
|
||||
msgid "does not match confirmation"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.no_assoc_constraint/3
|
||||
msgid "is still associated with this entry"
|
||||
msgstr ""
|
||||
|
||||
msgid "are still associated with this entry"
|
||||
msgstr ""
|
||||
|
||||
## From Ecto.Changeset.validate_length/3
|
||||
msgid "should be %{count} character(s)"
|
||||
msgid_plural "should be %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should have %{count} item(s)"
|
||||
msgid_plural "should have %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should be at least %{count} character(s)"
|
||||
msgid_plural "should be at least %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should have at least %{count} item(s)"
|
||||
msgid_plural "should have at least %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should be at most %{count} character(s)"
|
||||
msgid_plural "should be at most %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "should have at most %{count} item(s)"
|
||||
msgid_plural "should have at most %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
## From Ecto.Changeset.validate_number/3
|
||||
msgid "must be less than %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be greater than %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be less than or equal to %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be greater than or equal to %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be equal to %{number}"
|
||||
msgstr ""
|
0
apps/app/priv/repo/migrations/.keep
Normal file
0
apps/app/priv/repo/migrations/.keep
Normal file
32
apps/app/priv/templates/phx.gen.channel/channel.ex
Normal file
32
apps/app/priv/templates/phx.gen.channel/channel.ex
Normal file
|
@ -0,0 +1,32 @@
|
|||
defmodule <%= module %>Channel do
|
||||
use <%= web_module %>, :channel
|
||||
|
||||
@impl true
|
||||
def join("<%= singular %>:lobby", payload, socket) do
|
||||
if authorized?(payload) do
|
||||
{:ok, socket}
|
||||
else
|
||||
{:error, %{reason: "unauthorized"}}
|
||||
end
|
||||
end
|
||||
|
||||
# Channels can be used in a request/response fashion
|
||||
# by sending replies to requests from the client
|
||||
@impl true
|
||||
def handle_in("ping", payload, socket) do
|
||||
{:reply, {:ok, payload}, socket}
|
||||
end
|
||||
|
||||
# It is also common to receive messages from the client and
|
||||
# broadcast to everyone in the current topic (<%= singular %>:lobby).
|
||||
@impl true
|
||||
def handle_in("shout", payload, socket) do
|
||||
broadcast socket, "shout", payload
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
# Add authorization logic here as required.
|
||||
defp authorized?(_payload) do
|
||||
true
|
||||
end
|
||||
end
|
27
apps/app/priv/templates/phx.gen.channel/channel_test.exs
Normal file
27
apps/app/priv/templates/phx.gen.channel/channel_test.exs
Normal file
|
@ -0,0 +1,27 @@
|
|||
defmodule <%= module %>ChannelTest do
|
||||
use <%= web_module %>.ChannelCase
|
||||
|
||||
setup do
|
||||
{:ok, _, socket} =
|
||||
<%= web_module %>.UserSocket
|
||||
|> socket("user_id", %{some: :assign})
|
||||
|> subscribe_and_join(<%= module %>Channel, "<%= singular %>:lobby")
|
||||
|
||||
%{socket: socket}
|
||||
end
|
||||
|
||||
test "ping replies with status ok", %{socket: socket} do
|
||||
ref = push socket, "ping", %{"hello" => "there"}
|
||||
assert_reply ref, :ok, %{"hello" => "there"}
|
||||
end
|
||||
|
||||
test "shout broadcasts to <%= singular %>:lobby", %{socket: socket} do
|
||||
push socket, "shout", %{"hello" => "all"}
|
||||
assert_broadcast "shout", %{"hello" => "all"}
|
||||
end
|
||||
|
||||
test "broadcasts are pushed to the client", %{socket: socket} do
|
||||
broadcast_from! socket, "broadcast", %{"some" => "data"}
|
||||
assert_push "broadcast", %{"some" => "data"}
|
||||
end
|
||||
end
|
89
apps/app/priv/templates/phx.gen.context/access_no_schema.ex
Normal file
89
apps/app/priv/templates/phx.gen.context/access_no_schema.ex
Normal file
|
@ -0,0 +1,89 @@
|
|||
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
@doc """
|
||||
Returns the list of <%= schema.plural %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_<%= schema.plural %>()
|
||||
[%<%= inspect schema.alias %>{}, ...]
|
||||
|
||||
"""
|
||||
def list_<%= schema.plural %> do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single <%= schema.singular %>.
|
||||
|
||||
Raises if the <%= schema.human_singular %> does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_<%= schema.singular %>!(123)
|
||||
%<%= inspect schema.alias %>{}
|
||||
|
||||
"""
|
||||
def get_<%= schema.singular %>!(id), do: raise "TODO"
|
||||
|
||||
@doc """
|
||||
Creates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: bad_value})
|
||||
{:error, ...}
|
||||
|
||||
"""
|
||||
def create_<%= schema.singular %>(attrs \\ %{}) do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: new_value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: bad_value})
|
||||
{:error, ...}
|
||||
|
||||
"""
|
||||
def update_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a <%= inspect schema.alias %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:error, ...}
|
||||
|
||||
"""
|
||||
def delete_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>) do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns a data structure for tracking <%= schema.singular %> changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
%Todo{...}
|
||||
|
||||
"""
|
||||
def change_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, _attrs \\ %{}) do
|
||||
raise "TODO"
|
||||
end
|
8
apps/app/priv/templates/phx.gen.context/context.ex
Normal file
8
apps/app/priv/templates/phx.gen.context/context.ex
Normal file
|
@ -0,0 +1,8 @@
|
|||
defmodule <%= inspect context.module %> do
|
||||
@moduledoc """
|
||||
The <%= context.name %> context.
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
alias <%= inspect schema.repo %>
|
||||
end
|
5
apps/app/priv/templates/phx.gen.context/context_test.exs
Normal file
5
apps/app/priv/templates/phx.gen.context/context_test.exs
Normal file
|
@ -0,0 +1,5 @@
|
|||
defmodule <%= inspect context.module %>Test do
|
||||
use <%= inspect context.base_module %>.DataCase
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
end
|
11
apps/app/priv/templates/phx.gen.context/fixtures.ex
Normal file
11
apps/app/priv/templates/phx.gen.context/fixtures.ex
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
def <%= schema.singular %>_fixture(attrs \\ %{}) do
|
||||
{:ok, <%= schema.singular %>} =
|
||||
attrs
|
||||
|> Enum.into(%{
|
||||
<%= schema.params.create |> Enum.map(fn {key, val} -> " #{key}: #{inspect(val)}" end) |> Enum.join(",\n") %>
|
||||
})
|
||||
|> <%= inspect context.module %>.create_<%= schema.singular %>()
|
||||
|
||||
<%= schema.singular %>
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
defmodule <%= inspect context.module %>Fixtures do
|
||||
@moduledoc """
|
||||
This module defines test helpers for creating
|
||||
entities via the `<%= inspect context.module %>` context.
|
||||
"""
|
||||
end
|
96
apps/app/priv/templates/phx.gen.context/schema_access.ex
Normal file
96
apps/app/priv/templates/phx.gen.context/schema_access.ex
Normal file
|
@ -0,0 +1,96 @@
|
|||
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
@doc """
|
||||
Returns the list of <%= schema.plural %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_<%= schema.plural %>()
|
||||
[%<%= inspect schema.alias %>{}, ...]
|
||||
|
||||
"""
|
||||
def list_<%= schema.plural %> do
|
||||
Repo.all(<%= inspect schema.alias %>)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single <%= schema.singular %>.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the <%= schema.human_singular %> does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_<%= schema.singular %>!(123)
|
||||
%<%= inspect schema.alias %>{}
|
||||
|
||||
iex> get_<%= schema.singular %>!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_<%= schema.singular %>!(id), do: Repo.get!(<%= inspect schema.alias %>, id)
|
||||
|
||||
@doc """
|
||||
Creates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_<%= schema.singular %>(attrs \\ %{}) do
|
||||
%<%= inspect schema.alias %>{}
|
||||
|> <%= inspect schema.alias %>.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: new_value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
|
||||
<%= schema.singular %>
|
||||
|> <%= inspect schema.alias %>.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>) do
|
||||
Repo.delete(<%= schema.singular %>)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking <%= schema.singular %> changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
%Ecto.Changeset{data: %<%= inspect schema.alias %>{}}
|
||||
|
||||
"""
|
||||
def change_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs \\ %{}) do
|
||||
<%= inspect schema.alias %>.changeset(<%= schema.singular %>, attrs)
|
||||
end
|
54
apps/app/priv/templates/phx.gen.context/test_cases.exs
Normal file
54
apps/app/priv/templates/phx.gen.context/test_cases.exs
Normal file
|
@ -0,0 +1,54 @@
|
|||
|
||||
describe "<%= schema.plural %>" do
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
import <%= inspect context.module %>Fixtures
|
||||
|
||||
@invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>
|
||||
|
||||
test "list_<%= schema.plural %>/0 returns all <%= schema.plural %>" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert <%= inspect context.alias %>.list_<%= schema.plural %>() == [<%= schema.singular %>]
|
||||
end
|
||||
|
||||
test "get_<%= schema.singular %>!/1 returns the <%= schema.singular %> with given id" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) == <%= schema.singular %>
|
||||
end
|
||||
|
||||
test "create_<%= schema.singular %>/1 with valid data creates a <%= schema.singular %>" do
|
||||
valid_attrs = <%= inspect schema.params.create %>
|
||||
|
||||
assert {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} = <%= inspect context.alias %>.create_<%= schema.singular %>(valid_attrs)<%= for {field, value} <- schema.params.create do %>
|
||||
assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
|
||||
end
|
||||
|
||||
test "create_<%= schema.singular %>/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.create_<%= schema.singular %>(@invalid_attrs)
|
||||
end
|
||||
|
||||
test "update_<%= schema.singular %>/2 with valid data updates the <%= schema.singular %>" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
update_attrs = <%= inspect schema.params.update %>
|
||||
|
||||
assert {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, update_attrs)<%= for {field, value} <- schema.params.update do %>
|
||||
assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
|
||||
end
|
||||
|
||||
test "update_<%= schema.singular %>/2 with invalid data returns error changeset" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, @invalid_attrs)
|
||||
assert <%= schema.singular %> == <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id)
|
||||
end
|
||||
|
||||
test "delete_<%= schema.singular %>/1 deletes the <%= schema.singular %>" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert {:ok, %<%= inspect schema.alias %>{}} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
assert_raise Ecto.NoResultsError, fn -> <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) end
|
||||
end
|
||||
|
||||
test "change_<%= schema.singular %>/1 returns a <%= schema.singular %> changeset" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert %Ecto.Changeset{} = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
end
|
||||
end
|
16
apps/app/priv/templates/phx.gen.embedded/embedded_schema.ex
Normal file
16
apps/app/priv/templates/phx.gen.embedded/embedded_schema.ex
Normal file
|
@ -0,0 +1,16 @@
|
|||
defmodule <%= inspect schema.module %> do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
embedded_schema do
|
||||
<%= for {k, v} <- schema.types do %> field <%= inspect k %>, <%= inspect v %><%= schema.defaults[k] %>
|
||||
<% end %> end
|
||||
|
||||
@doc false
|
||||
def changeset(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
|
||||
<%= schema.singular %>
|
||||
|> cast(attrs, [<%= Enum.map_join(schema.attrs, ", ", &inspect(elem(&1, 0))) %>])
|
||||
|> validate_required([<%= Enum.map_join(schema.attrs, ", ", &inspect(elem(&1, 0))) %>])
|
||||
end
|
||||
end
|
62
apps/app/priv/templates/phx.gen.html/controller.ex
Normal file
62
apps/app/priv/templates/phx.gen.html/controller.ex
Normal file
|
@ -0,0 +1,62 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Controller do
|
||||
use <%= inspect context.web_module %>, :controller
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
def index(conn, _params) do
|
||||
<%= schema.plural %> = <%= inspect context.alias %>.list_<%= schema.plural %>()
|
||||
render(conn, "index.html", <%= schema.plural %>: <%= schema.plural %>)
|
||||
end
|
||||
|
||||
def new(conn, _params) do
|
||||
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(%<%= inspect schema.alias %>{})
|
||||
render(conn, "new.html", changeset: changeset)
|
||||
end
|
||||
|
||||
def create(conn, %{<%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
case <%= inspect context.alias %>.create_<%= schema.singular %>(<%= schema.singular %>_params) do
|
||||
{:ok, <%= schema.singular %>} ->
|
||||
conn
|
||||
|> put_flash(:info, "<%= schema.human_singular %> created successfully.")
|
||||
|> redirect(to: Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
render(conn, "new.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
render(conn, "show.html", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
|
||||
def edit(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
render(conn, "edit.html", <%= schema.singular %>: <%= schema.singular %>, changeset: changeset)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, <%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
|
||||
case <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, <%= schema.singular %>_params) do
|
||||
{:ok, <%= schema.singular %>} ->
|
||||
conn
|
||||
|> put_flash(:info, "<%= schema.human_singular %> updated successfully.")
|
||||
|> redirect(to: Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
render(conn, "edit.html", <%= schema.singular %>: <%= schema.singular %>, changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
{:ok, _<%= schema.singular %>} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
|
||||
conn
|
||||
|> put_flash(:info, "<%= schema.human_singular %> deleted successfully.")
|
||||
|> redirect(to: Routes.<%= schema.route_helper %>_path(conn, :index))
|
||||
end
|
||||
end
|
84
apps/app/priv/templates/phx.gen.html/controller_test.exs
Normal file
84
apps/app/priv/templates/phx.gen.html/controller_test.exs
Normal file
|
@ -0,0 +1,84 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>ControllerTest do
|
||||
use <%= inspect context.web_module %>.ConnCase
|
||||
|
||||
import <%= inspect context.module %>Fixtures
|
||||
|
||||
@create_attrs <%= inspect schema.params.create %>
|
||||
@update_attrs <%= inspect schema.params.update %>
|
||||
@invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>
|
||||
|
||||
describe "index" do
|
||||
test "lists all <%= schema.plural %>", %{conn: conn} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :index))
|
||||
assert html_response(conn, 200) =~ "Listing <%= schema.human_plural %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "new <%= schema.singular %>" do
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :new))
|
||||
assert html_response(conn, 200) =~ "New <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create <%= schema.singular %>" do
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @create_attrs)
|
||||
|
||||
assert %{id: id} = redirected_params(conn)
|
||||
assert redirected_to(conn) == Routes.<%= schema.route_helper %>_path(conn, :show, id)
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, id))
|
||||
assert html_response(conn, 200) =~ "Show <%= schema.human_singular %>"
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @invalid_attrs)
|
||||
assert html_response(conn, 200) =~ "New <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "edit <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "renders form for editing chosen <%= schema.singular %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :edit, <%= schema.singular %>))
|
||||
assert html_response(conn, 200) =~ "Edit <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "update <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @update_attrs)
|
||||
assert redirected_to(conn) == Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>)
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))<%= if schema.string_attr do %>
|
||||
assert html_response(conn, 200) =~ <%= inspect Mix.Phoenix.Schema.default_param(schema, :update) %><% else %>
|
||||
assert html_response(conn, 200)<% end %>
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @invalid_attrs)
|
||||
assert html_response(conn, 200) =~ "Edit <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "deletes chosen <%= schema.singular %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = delete(conn, Routes.<%= schema.route_helper %>_path(conn, :delete, <%= schema.singular %>))
|
||||
assert redirected_to(conn) == Routes.<%= schema.route_helper %>_path(conn, :index)
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp create_<%= schema.singular %>(_) do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
%{<%= schema.singular %>: <%= schema.singular %>}
|
||||
end
|
||||
end
|
5
apps/app/priv/templates/phx.gen.html/edit.html.eex
Normal file
5
apps/app/priv/templates/phx.gen.html/edit.html.eex
Normal file
|
@ -0,0 +1,5 @@
|
|||
<h1>Edit <%= schema.human_singular %></h1>
|
||||
|
||||
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :update, @<%= schema.singular %>)) %>
|
||||
|
||||
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index) %></span>
|
15
apps/app/priv/templates/phx.gen.html/form.html.eex
Normal file
15
apps/app/priv/templates/phx.gen.html/form.html.eex
Normal file
|
@ -0,0 +1,15 @@
|
|||
<%%= 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 %>
|
||||
<%= for {label, input, error} <- inputs, input do %>
|
||||
<%= label %>
|
||||
<%= input %>
|
||||
<%= error %>
|
||||
<% end %>
|
||||
<div>
|
||||
<%%= submit "Save" %>
|
||||
</div>
|
||||
<%% end %>
|
26
apps/app/priv/templates/phx.gen.html/index.html.eex
Normal file
26
apps/app/priv/templates/phx.gen.html/index.html.eex
Normal file
|
@ -0,0 +1,26 @@
|
|||
<h1>Listing <%= schema.human_plural %></h1>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<%= for {k, _} <- schema.attrs do %> <th><%= Phoenix.Naming.humanize(Atom.to_string(k)) %></th>
|
||||
<% end %>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%%= for <%= schema.singular %> <- @<%= schema.plural %> do %>
|
||||
<tr>
|
||||
<%= for {k, _} <- schema.attrs do %> <td><%%= <%= schema.singular %>.<%= k %> %></td>
|
||||
<% end %>
|
||||
<td>
|
||||
<span><%%= link "Show", to: Routes.<%= schema.route_helper %>_path(@conn, :show, <%= schema.singular %>) %></span>
|
||||
<span><%%= link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, <%= schema.singular %>) %></span>
|
||||
<span><%%= link "Delete", to: Routes.<%= schema.route_helper %>_path(@conn, :delete, <%= schema.singular %>), method: :delete, data: [confirm: "Are you sure?"] %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<%% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<span><%%= link "New <%= schema.human_singular %>", to: Routes.<%= schema.route_helper %>_path(@conn, :new) %></span>
|
5
apps/app/priv/templates/phx.gen.html/new.html.eex
Normal file
5
apps/app/priv/templates/phx.gen.html/new.html.eex
Normal file
|
@ -0,0 +1,5 @@
|
|||
<h1>New <%= schema.human_singular %></h1>
|
||||
|
||||
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :create)) %>
|
||||
|
||||
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index) %></span>
|
13
apps/app/priv/templates/phx.gen.html/show.html.eex
Normal file
13
apps/app/priv/templates/phx.gen.html/show.html.eex
Normal file
|
@ -0,0 +1,13 @@
|
|||
<h1>Show <%= schema.human_singular %></h1>
|
||||
|
||||
<ul>
|
||||
<%= for {k, _} <- schema.attrs do %>
|
||||
<li>
|
||||
<strong><%= Phoenix.Naming.humanize(Atom.to_string(k)) %>:</strong>
|
||||
<%%= @<%= schema.singular %>.<%= k %> %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<span><%%= link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, @<%= schema.singular %>) %></span>
|
||||
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index) %></span>
|
3
apps/app/priv/templates/phx.gen.html/view.ex
Normal file
3
apps/app/priv/templates/phx.gen.html/view.ex
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>View do
|
||||
use <%= inspect context.web_module %>, :view
|
||||
end
|
19
apps/app/priv/templates/phx.gen.json/changeset_view.ex
Normal file
19
apps/app/priv/templates/phx.gen.json/changeset_view.ex
Normal file
|
@ -0,0 +1,19 @@
|
|||
defmodule <%= inspect context.web_module %>.ChangesetView do
|
||||
use <%= inspect context.web_module %>, :view
|
||||
|
||||
@doc """
|
||||
Traverses and translates changeset errors.
|
||||
|
||||
See `Ecto.Changeset.traverse_errors/2` and
|
||||
`<%= inspect context.web_module %>.ErrorHelpers.translate_error/1` for more details.
|
||||
"""
|
||||
def translate_errors(changeset) do
|
||||
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
|
||||
end
|
||||
|
||||
def render("error.json", %{changeset: changeset}) do
|
||||
# When encoded, the changeset returns its errors
|
||||
# as a JSON object. So we just pass it forward.
|
||||
%{errors: translate_errors(changeset)}
|
||||
end
|
||||
end
|
43
apps/app/priv/templates/phx.gen.json/controller.ex
Normal file
43
apps/app/priv/templates/phx.gen.json/controller.ex
Normal file
|
@ -0,0 +1,43 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Controller do
|
||||
use <%= inspect context.web_module %>, :controller
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
action_fallback <%= inspect context.web_module %>.FallbackController
|
||||
|
||||
def index(conn, _params) do
|
||||
<%= schema.plural %> = <%= inspect context.alias %>.list_<%= schema.plural %>()
|
||||
render(conn, "index.json", <%= schema.plural %>: <%= schema.plural %>)
|
||||
end
|
||||
|
||||
def create(conn, %{<%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
with {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} <- <%= inspect context.alias %>.create_<%= schema.singular %>(<%= schema.singular %>_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
|> render("show.json", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
render(conn, "show.json", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, <%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
|
||||
with {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} <- <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, <%= schema.singular %>_params) do
|
||||
render(conn, "show.json", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
|
||||
with {:ok, %<%= inspect schema.alias %>{}} <- <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
84
apps/app/priv/templates/phx.gen.json/controller_test.exs
Normal file
84
apps/app/priv/templates/phx.gen.json/controller_test.exs
Normal file
|
@ -0,0 +1,84 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>ControllerTest do
|
||||
use <%= inspect context.web_module %>.ConnCase
|
||||
|
||||
import <%= inspect context.module %>Fixtures
|
||||
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
@create_attrs %{
|
||||
<%= schema.params.create |> Enum.map(fn {key, val} -> " #{key}: #{inspect(val)}" end) |> Enum.join(",\n") %>
|
||||
}
|
||||
@update_attrs %{
|
||||
<%= schema.params.update |> Enum.map(fn {key, val} -> " #{key}: #{inspect(val)}" end) |> Enum.join(",\n") %>
|
||||
}
|
||||
@invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>
|
||||
|
||||
setup %{conn: conn} do
|
||||
{:ok, conn: put_req_header(conn, "accept", "application/json")}
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
test "lists all <%= schema.plural %>", %{conn: conn} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :index))
|
||||
assert json_response(conn, 200)["data"] == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "create <%= schema.singular %>" do
|
||||
test "renders <%= schema.singular %> when data is valid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @create_attrs)
|
||||
assert %{"id" => id} = json_response(conn, 201)["data"]
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, id))
|
||||
|
||||
assert %{
|
||||
"id" => id<%= for {key, val} <- schema.params.create |> Phoenix.json_library().encode!() |> Phoenix.json_library().decode!() do %>,
|
||||
"<%= key %>" => <%= inspect(val) %><% end %>
|
||||
} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @invalid_attrs)
|
||||
assert json_response(conn, 422)["errors"] != %{}
|
||||
end
|
||||
end
|
||||
|
||||
describe "update <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "renders <%= schema.singular %> when data is valid", %{conn: conn, <%= schema.singular %>: %<%= inspect schema.alias %>{id: id} = <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @update_attrs)
|
||||
assert %{"id" => ^id} = json_response(conn, 200)["data"]
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, id))
|
||||
|
||||
assert %{
|
||||
"id" => id<%= for {key, val} <- schema.params.update |> Phoenix.json_library().encode!() |> Phoenix.json_library().decode!() do %>,
|
||||
"<%= key %>" => <%= inspect(val) %><% end %>
|
||||
} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @invalid_attrs)
|
||||
assert json_response(conn, 422)["errors"] != %{}
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "deletes chosen <%= schema.singular %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = delete(conn, Routes.<%= schema.route_helper %>_path(conn, :delete, <%= schema.singular %>))
|
||||
assert response(conn, 204)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp create_<%= schema.singular %>(_) do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
%{<%= schema.singular %>: <%= schema.singular %>}
|
||||
end
|
||||
end
|
24
apps/app/priv/templates/phx.gen.json/fallback_controller.ex
Normal file
24
apps/app/priv/templates/phx.gen.json/fallback_controller.ex
Normal file
|
@ -0,0 +1,24 @@
|
|||
defmodule <%= inspect context.web_module %>.FallbackController do
|
||||
@moduledoc """
|
||||
Translates controller action results into valid `Plug.Conn` responses.
|
||||
|
||||
See `Phoenix.Controller.action_fallback/1` for more details.
|
||||
"""
|
||||
use <%= inspect context.web_module %>, :controller
|
||||
|
||||
<%= if schema.generate? do %># This clause handles errors returned by Ecto's insert/update/delete.
|
||||
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> put_view(<%= inspect context.web_module %>.ChangesetView)
|
||||
|> render("error.json", changeset: changeset)
|
||||
end
|
||||
|
||||
<% end %># This clause is an example of how to handle resources that cannot be found.
|
||||
def call(conn, {:error, :not_found}) do
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> put_view(<%= inspect context.web_module %>.ErrorView)
|
||||
|> render(:"404")
|
||||
end
|
||||
end
|
17
apps/app/priv/templates/phx.gen.json/view.ex
Normal file
17
apps/app/priv/templates/phx.gen.json/view.ex
Normal file
|
@ -0,0 +1,17 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>View do
|
||||
use <%= inspect context.web_module %>, :view
|
||||
alias <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>View
|
||||
|
||||
def render("index.json", %{<%= schema.plural %>: <%= schema.plural %>}) do
|
||||
%{data: render_many(<%= schema.plural %>, <%= inspect schema.alias %>View, "<%= schema.singular %>.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{<%= schema.singular %>: <%= schema.singular %>}) do
|
||||
%{data: render_one(<%= schema.singular %>, <%= inspect schema.alias %>View, "<%= schema.singular %>.json")}
|
||||
end
|
||||
|
||||
def render("<%= schema.singular %>.json", %{<%= schema.singular %>: <%= schema.singular %>}) do
|
||||
%{id: <%= schema.singular %>.id<%= for {k, _} <- schema.attrs do %>,
|
||||
<%= k %>: <%= schema.singular %>.<%= k %><% end %>}
|
||||
end
|
||||
end
|
55
apps/app/priv/templates/phx.gen.live/form_component.ex
Normal file
55
apps/app/priv/templates/phx.gen.live/form_component.ex
Normal file
|
@ -0,0 +1,55 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.FormComponent do
|
||||
use <%= inspect context.web_module %>, :live_component
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
|
||||
@impl true
|
||||
def update(%{<%= schema.singular %>: <%= schema.singular %>} = assigns, socket) do
|
||||
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("validate", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
|
||||
changeset =
|
||||
socket.assigns.<%= schema.singular %>
|
||||
|> <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>_params)
|
||||
|> Map.put(:action, :validate)
|
||||
|
||||
{:noreply, assign(socket, :changeset, changeset)}
|
||||
end
|
||||
|
||||
def handle_event("save", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
|
||||
save_<%= schema.singular %>(socket, socket.assigns.action, <%= schema.singular %>_params)
|
||||
end
|
||||
|
||||
defp save_<%= schema.singular %>(socket, :edit, <%= schema.singular %>_params) do
|
||||
case <%= inspect context.alias %>.update_<%= schema.singular %>(socket.assigns.<%= schema.singular %>, <%= schema.singular %>_params) do
|
||||
{:ok, _<%= schema.singular %>} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "<%= schema.human_singular %> updated successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, assign(socket, :changeset, changeset)}
|
||||
end
|
||||
end
|
||||
|
||||
defp save_<%= schema.singular %>(socket, :new, <%= schema.singular %>_params) do
|
||||
case <%= inspect context.alias %>.create_<%= schema.singular %>(<%= schema.singular %>_params) do
|
||||
{:ok, _<%= schema.singular %>} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "<%= schema.human_singular %> created successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, assign(socket, changeset: changeset)}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
<h2><%%= @title %></h2>
|
||||
|
||||
<%%= f = form_for @changeset, "#",
|
||||
id: "<%= schema.singular %>-form",
|
||||
phx_target: @myself,
|
||||
phx_change: "validate",
|
||||
phx_submit: "save" %>
|
||||
<%= for {label, input, error} <- inputs, input do %>
|
||||
<%= label %>
|
||||
<%= input %>
|
||||
<%= error %>
|
||||
<% end %>
|
||||
<%%= submit "Save", phx_disable_with: "Saving..." %>
|
||||
</form>
|
46
apps/app/priv/templates/phx.gen.live/index.ex
Normal file
46
apps/app/priv/templates/phx.gen.live/index.ex
Normal file
|
@ -0,0 +1,46 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.Index do
|
||||
use <%= inspect context.web_module %>, :live_view
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, assign(socket, :<%= schema.collection %>, list_<%= schema.plural %>())}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_params(params, _url, socket) do
|
||||
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
|
||||
end
|
||||
|
||||
defp apply_action(socket, :edit, %{"id" => id}) do
|
||||
socket
|
||||
|> assign(:page_title, "Edit <%= schema.human_singular %>")
|
||||
|> assign(:<%= schema.singular %>, <%= inspect context.alias %>.get_<%= schema.singular %>!(id))
|
||||
end
|
||||
|
||||
defp apply_action(socket, :new, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "New <%= schema.human_singular %>")
|
||||
|> assign(:<%= schema.singular %>, %<%= inspect schema.alias %>{})
|
||||
end
|
||||
|
||||
defp apply_action(socket, :index, _params) do
|
||||
socket
|
||||
|> assign(:page_title, "Listing <%= schema.human_plural %>")
|
||||
|> assign(:<%= schema.singular %>, nil)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("delete", %{"id" => id}, socket) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
{:ok, _} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
|
||||
{:noreply, assign(socket, :<%= schema.collection %>, list_<%=schema.plural %>())}
|
||||
end
|
||||
|
||||
defp list_<%= schema.plural %> do
|
||||
<%= inspect context.alias %>.list_<%= schema.plural %>()
|
||||
end
|
||||
end
|
35
apps/app/priv/templates/phx.gen.live/index.html.leex
Normal file
35
apps/app/priv/templates/phx.gen.live/index.html.leex
Normal file
|
@ -0,0 +1,35 @@
|
|||
<h1>Listing <%= schema.human_plural %></h1>
|
||||
|
||||
<%%= if @live_action in [:new, :edit] do %>
|
||||
<%%= live_modal @socket, <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.FormComponent,
|
||||
id: @<%= schema.singular %>.id || :new,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
<%= schema.singular %>: @<%= schema.singular %>,
|
||||
return_to: Routes.<%= schema.route_helper %>_index_path(@socket, :index) %>
|
||||
<%% end %>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<%= for {k, _} <- schema.attrs do %> <th><%= Phoenix.Naming.humanize(Atom.to_string(k)) %></th>
|
||||
<% end %>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="<%= schema.plural %>">
|
||||
<%%= for <%= schema.singular %> <- @<%= schema.collection %> do %>
|
||||
<tr id="<%= schema.singular %>-<%%= <%= schema.singular %>.id %>">
|
||||
<%= for {k, _} <- schema.attrs do %> <td><%%= <%= schema.singular %>.<%= k %> %></td>
|
||||
<% end %>
|
||||
<td>
|
||||
<span><%%= live_redirect "Show", to: Routes.<%= schema.route_helper %>_show_path(@socket, :show, <%= schema.singular %>) %></span>
|
||||
<span><%%= live_patch "Edit", to: Routes.<%= schema.route_helper %>_index_path(@socket, :edit, <%= schema.singular %>) %></span>
|
||||
<span><%%= link "Delete", to: "#", phx_click: "delete", phx_value_id: <%= schema.singular %>.id, data: [confirm: "Are you sure?"] %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<%% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<span><%%= live_patch "New <%= schema.human_singular %>", to: Routes.<%= schema.route_helper %>_index_path(@socket, :new) %></span>
|
23
apps/app/priv/templates/phx.gen.live/live_helpers.ex
Normal file
23
apps/app/priv/templates/phx.gen.live/live_helpers.ex
Normal file
|
@ -0,0 +1,23 @@
|
|||
defmodule <%= inspect context.web_module %>.LiveHelpers do
|
||||
import Phoenix.LiveView.Helpers
|
||||
|
||||
@doc """
|
||||
Renders a component inside the `<%= inspect context.web_module %>.ModalComponent` component.
|
||||
|
||||
The rendered modal receives a `:return_to` option to properly update
|
||||
the URL when the modal is closed.
|
||||
|
||||
## Examples
|
||||
|
||||
<%%= live_modal @socket, <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.FormComponent,
|
||||
id: @<%= schema.singular %>.id || :new,
|
||||
action: @live_action,
|
||||
<%= schema.singular %>: @<%= schema.singular %>,
|
||||
return_to: Routes.<%= schema.singular %>_index_path(@socket, :index) %>
|
||||
"""
|
||||
def live_modal(socket, component, opts) do
|
||||
path = Keyword.fetch!(opts, :return_to)
|
||||
modal_opts = [id: :modal, return_to: path, component: component, opts: opts]
|
||||
live_component(socket, <%= inspect context.web_module %>.ModalComponent, modal_opts)
|
||||
end
|
||||
end
|
110
apps/app/priv/templates/phx.gen.live/live_test.exs
Normal file
110
apps/app/priv/templates/phx.gen.live/live_test.exs
Normal file
|
@ -0,0 +1,110 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>LiveTest do
|
||||
use <%= inspect context.web_module %>.ConnCase
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import <%= inspect context.module %>Fixtures
|
||||
|
||||
@create_attrs <%= inspect schema.params.create %>
|
||||
@update_attrs <%= inspect schema.params.update %>
|
||||
@invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>
|
||||
|
||||
defp create_<%= schema.singular %>(_) do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
%{<%= schema.singular %>: <%= schema.singular %>}
|
||||
end
|
||||
|
||||
describe "Index" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "lists all <%= schema.plural %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
{:ok, _index_live, html} = live(conn, Routes.<%= schema.route_helper %>_index_path(conn, :index))
|
||||
|
||||
assert html =~ "Listing <%= schema.human_plural %>"<%= if schema.string_attr do %>
|
||||
assert html =~ <%= schema.singular %>.<%= schema.string_attr %><% end %>
|
||||
end
|
||||
|
||||
test "saves new <%= schema.singular %>", %{conn: conn} do
|
||||
{:ok, index_live, _html} = live(conn, Routes.<%= schema.route_helper %>_index_path(conn, :index))
|
||||
|
||||
assert index_live |> element("a", "New <%= schema.human_singular %>") |> render_click() =~
|
||||
"New <%= schema.human_singular %>"
|
||||
|
||||
assert_patch(index_live, Routes.<%= schema.route_helper %>_index_path(conn, :new))
|
||||
|
||||
assert index_live
|
||||
|> form("#<%= schema.singular %>-form", <%= schema.singular %>: @invalid_attrs)
|
||||
|> render_change() =~ "can't be blank"
|
||||
|
||||
{:ok, _, html} =
|
||||
index_live
|
||||
|> form("#<%= schema.singular %>-form", <%= schema.singular %>: @create_attrs)
|
||||
|> render_submit()
|
||||
|> follow_redirect(conn, Routes.<%= schema.route_helper %>_index_path(conn, :index))
|
||||
|
||||
assert html =~ "<%= schema.human_singular %> created successfully"<%= if schema.string_attr do %>
|
||||
assert html =~ "some <%= schema.string_attr %>"<% end %>
|
||||
end
|
||||
|
||||
test "updates <%= schema.singular %> in listing", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
{:ok, index_live, _html} = live(conn, Routes.<%= schema.route_helper %>_index_path(conn, :index))
|
||||
|
||||
assert index_live |> element("#<%= schema.singular %>-#{<%= schema.singular %>.id} a", "Edit") |> render_click() =~
|
||||
"Edit <%= schema.human_singular %>"
|
||||
|
||||
assert_patch(index_live, Routes.<%= schema.route_helper %>_index_path(conn, :edit, <%= schema.singular %>))
|
||||
|
||||
assert index_live
|
||||
|> form("#<%= schema.singular %>-form", <%= schema.singular %>: @invalid_attrs)
|
||||
|> render_change() =~ "can't be blank"
|
||||
|
||||
{:ok, _, html} =
|
||||
index_live
|
||||
|> form("#<%= schema.singular %>-form", <%= schema.singular %>: @update_attrs)
|
||||
|> render_submit()
|
||||
|> follow_redirect(conn, Routes.<%= schema.route_helper %>_index_path(conn, :index))
|
||||
|
||||
assert html =~ "<%= schema.human_singular %> updated successfully"<%= if schema.string_attr do %>
|
||||
assert html =~ "some updated <%= schema.string_attr %>"<% end %>
|
||||
end
|
||||
|
||||
test "deletes <%= schema.singular %> in listing", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
{:ok, index_live, _html} = live(conn, Routes.<%= schema.route_helper %>_index_path(conn, :index))
|
||||
|
||||
assert index_live |> element("#<%= schema.singular %>-#{<%= schema.singular %>.id} a", "Delete") |> render_click()
|
||||
refute has_element?(index_live, "#<%= schema.singular %>-#{<%= schema.singular %>.id}")
|
||||
end
|
||||
end
|
||||
|
||||
describe "Show" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "displays <%= schema.singular %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
{:ok, _show_live, html} = live(conn, Routes.<%= schema.route_helper %>_show_path(conn, :show, <%= schema.singular %>))
|
||||
|
||||
assert html =~ "Show <%= schema.human_singular %>"<%= if schema.string_attr do %>
|
||||
assert html =~ <%= schema.singular %>.<%= schema.string_attr %><% end %>
|
||||
end
|
||||
|
||||
test "updates <%= schema.singular %> within modal", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
{:ok, show_live, _html} = live(conn, Routes.<%= schema.route_helper %>_show_path(conn, :show, <%= schema.singular %>))
|
||||
|
||||
assert show_live |> element("a", "Edit") |> render_click() =~
|
||||
"Edit <%= schema.human_singular %>"
|
||||
|
||||
assert_patch(show_live, Routes.<%= schema.route_helper %>_show_path(conn, :edit, <%= schema.singular %>))
|
||||
|
||||
assert show_live
|
||||
|> form("#<%= schema.singular %>-form", <%= schema.singular %>: @invalid_attrs)
|
||||
|> render_change() =~ "can't be blank"
|
||||
|
||||
{:ok, _, html} =
|
||||
show_live
|
||||
|> form("#<%= schema.singular %>-form", <%= schema.singular %>: @update_attrs)
|
||||
|> render_submit()
|
||||
|> follow_redirect(conn, Routes.<%= schema.route_helper %>_show_path(conn, :show, <%= schema.singular %>))
|
||||
|
||||
assert html =~ "<%= schema.human_singular %> updated successfully"<%= if schema.string_attr do %>
|
||||
assert html =~ "some updated <%= schema.string_attr %>"<% end %>
|
||||
end
|
||||
end
|
||||
end
|
26
apps/app/priv/templates/phx.gen.live/modal_component.ex
Normal file
26
apps/app/priv/templates/phx.gen.live/modal_component.ex
Normal file
|
@ -0,0 +1,26 @@
|
|||
defmodule <%= inspect context.web_module %>.ModalComponent do
|
||||
use <%= inspect context.web_module %>, :live_component
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~L"""
|
||||
<div id="<%%= @id %>" class="phx-modal"
|
||||
phx-capture-click="close"
|
||||
phx-window-keydown="close"
|
||||
phx-key="escape"
|
||||
phx-target="#<%%= @id %>"
|
||||
phx-page-loading>
|
||||
|
||||
<div class="phx-modal-content">
|
||||
<%%= live_patch raw("×"), to: @return_to, class: "phx-modal-close" %>
|
||||
<%%= live_component @socket, @component, @opts %>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("close", _, socket) do
|
||||
{:noreply, push_patch(socket, to: socket.assigns.return_to)}
|
||||
end
|
||||
end
|
21
apps/app/priv/templates/phx.gen.live/show.ex
Normal file
21
apps/app/priv/templates/phx.gen.live/show.ex
Normal file
|
@ -0,0 +1,21 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.Show do
|
||||
use <%= inspect context.web_module %>, :live_view
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_params(%{"id" => id}, _, socket) do
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:page_title, page_title(socket.assigns.live_action))
|
||||
|> assign(:<%= schema.singular %>, <%= inspect context.alias %>.get_<%= schema.singular %>!(id))}
|
||||
end
|
||||
|
||||
defp page_title(:show), do: "Show <%= schema.human_singular %>"
|
||||
defp page_title(:edit), do: "Edit <%= schema.human_singular %>"
|
||||
end
|
22
apps/app/priv/templates/phx.gen.live/show.html.leex
Normal file
22
apps/app/priv/templates/phx.gen.live/show.html.leex
Normal file
|
@ -0,0 +1,22 @@
|
|||
<h1>Show <%= schema.human_singular %></h1>
|
||||
|
||||
<%%= if @live_action in [:edit] do %>
|
||||
<%%= live_modal @socket, <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.FormComponent,
|
||||
id: @<%= schema.singular %>.id,
|
||||
title: @page_title,
|
||||
action: @live_action,
|
||||
<%= schema.singular %>: @<%= schema.singular %>,
|
||||
return_to: Routes.<%= schema.route_helper %>_show_path(@socket, :show, @<%= schema.singular %>) %>
|
||||
<%% end %>
|
||||
|
||||
<ul>
|
||||
<%= for {k, _} <- schema.attrs do %>
|
||||
<li>
|
||||
<strong><%= Phoenix.Naming.humanize(Atom.to_string(k)) %>:</strong>
|
||||
<%%= @<%= schema.singular %>.<%= k %> %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<span><%%= live_patch "Edit", to: Routes.<%= schema.route_helper %>_show_path(@socket, :edit, @<%= schema.singular %>), class: "button" %></span>
|
||||
<span><%%= live_redirect "Back", to: Routes.<%= schema.route_helper %>_index_path(@socket, :index) %></span>
|
10
apps/app/priv/templates/phx.gen.presence/presence.ex
Normal file
10
apps/app/priv/templates/phx.gen.presence/presence.ex
Normal file
|
@ -0,0 +1,10 @@
|
|||
defmodule <%= module %> do
|
||||
@moduledoc """
|
||||
Provides presence tracking to channels and processes.
|
||||
|
||||
See the [`Phoenix.Presence`](http://hexdocs.pm/phoenix/Phoenix.Presence.html)
|
||||
docs for more details.
|
||||
"""
|
||||
use Phoenix.Presence, otp_app: <%= inspect otp_app %>,
|
||||
pubsub_server: <%= inspect pubsub_server %>
|
||||
end
|
15
apps/app/priv/templates/phx.gen.schema/migration.exs
Normal file
15
apps/app/priv/templates/phx.gen.schema/migration.exs
Normal file
|
@ -0,0 +1,15 @@
|
|||
defmodule <%= inspect schema.repo %>.Migrations.Create<%= Macro.camelize(schema.table) %> do
|
||||
use <%= inspect schema.migration_module %>
|
||||
|
||||
def change do
|
||||
create table(:<%= schema.table %><%= if schema.binary_id do %>, primary_key: false<% end %>) do
|
||||
<%= if schema.binary_id do %> add :id, :binary_id, primary_key: true
|
||||
<% end %><%= for {k, v} <- schema.attrs do %> add <%= inspect k %>, <%= inspect v %><%= schema.migration_defaults[k] %>
|
||||
<% end %><%= for {_, i, _, s} <- schema.assocs do %> add <%= inspect(i) %>, references(<%= inspect(s) %>, on_delete: :nothing<%= if schema.binary_id do %>, type: :binary_id<% end %>)
|
||||
<% end %>
|
||||
timestamps()
|
||||
end
|
||||
<%= for index <- schema.indexes do %>
|
||||
<%= index %><% end %>
|
||||
end
|
||||
end
|
21
apps/app/priv/templates/phx.gen.schema/schema.ex
Normal file
21
apps/app/priv/templates/phx.gen.schema/schema.ex
Normal file
|
@ -0,0 +1,21 @@
|
|||
defmodule <%= inspect schema.module %> do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
<%= if schema.binary_id do %>
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id<% end %>
|
||||
schema <%= inspect schema.table %> do
|
||||
<%= for {k, v} <- schema.types do %> field <%= inspect k %>, <%= inspect v %><%= schema.defaults[k] %>
|
||||
<% end %><%= for {_, k, _, _} <- schema.assocs do %> field <%= inspect k %>, <%= if schema.binary_id do %>:binary_id<% else %>:id<% end %>
|
||||
<% end %>
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(<%= schema.singular %>, attrs) do
|
||||
<%= schema.singular %>
|
||||
|> cast(attrs, [<%= Enum.map_join(schema.attrs, ", ", &inspect(elem(&1, 0))) %>])
|
||||
|> validate_required([<%= Enum.map_join(schema.attrs, ", ", &inspect(elem(&1, 0))) %>])
|
||||
<%= for k <- schema.uniques do %> |> unique_constraint(<%= inspect k %>)
|
||||
<% end %> end
|
||||
end
|
8
apps/app/test/app/controllers/page_controller_test.exs
Normal file
8
apps/app/test/app/controllers/page_controller_test.exs
Normal file
|
@ -0,0 +1,8 @@
|
|||
defmodule App.PageControllerTest do
|
||||
use App.ConnCase
|
||||
|
||||
test "GET /", %{conn: conn} do
|
||||
conn = get(conn, "/")
|
||||
assert html_response(conn, 200) =~ "Welcome to Phoenix!"
|
||||
end
|
||||
end
|
14
apps/app/test/app/views/error_view_test.exs
Normal file
14
apps/app/test/app/views/error_view_test.exs
Normal file
|
@ -0,0 +1,14 @@
|
|||
defmodule App.ErrorViewTest do
|
||||
use App.ConnCase, async: true
|
||||
|
||||
# Bring render/3 and render_to_string/3 for testing custom views
|
||||
import Phoenix.View
|
||||
|
||||
test "renders 404.html" do
|
||||
assert render_to_string(App.ErrorView, "404.html", []) == "Not Found"
|
||||
end
|
||||
|
||||
test "renders 500.html" do
|
||||
assert render_to_string(App.ErrorView, "500.html", []) == "Internal Server Error"
|
||||
end
|
||||
end
|
8
apps/app/test/app/views/layout_view_test.exs
Normal file
8
apps/app/test/app/views/layout_view_test.exs
Normal file
|
@ -0,0 +1,8 @@
|
|||
defmodule App.LayoutViewTest do
|
||||
use App.ConnCase, async: true
|
||||
|
||||
# When testing helpers, you may want to import Phoenix.HTML and
|
||||
# use functions such as safe_to_string() to convert the helper
|
||||
# result into an HTML string.
|
||||
# import Phoenix.HTML
|
||||
end
|
3
apps/app/test/app/views/page_view_test.exs
Normal file
3
apps/app/test/app/views/page_view_test.exs
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule App.PageViewTest do
|
||||
use App.ConnCase, async: true
|
||||
end
|
40
apps/app/test/support/channel_case.ex
Normal file
40
apps/app/test/support/channel_case.ex
Normal file
|
@ -0,0 +1,40 @@
|
|||
defmodule App.ChannelCase do
|
||||
@moduledoc """
|
||||
This module defines the test case to be used by
|
||||
channel tests.
|
||||
|
||||
Such tests rely on `Phoenix.ChannelTest` and also
|
||||
import other functionality to make it easier
|
||||
to build common data structures and query the data layer.
|
||||
|
||||
Finally, if the test case interacts with the database,
|
||||
we enable the SQL sandbox, so changes done to the database
|
||||
are reverted at the end of every test. If you are using
|
||||
PostgreSQL, you can even run database tests asynchronously
|
||||
by setting `use App.ChannelCase, async: true`, although
|
||||
this option is not recommended for other databases.
|
||||
"""
|
||||
|
||||
use ExUnit.CaseTemplate
|
||||
|
||||
using do
|
||||
quote do
|
||||
# Import conveniences for testing with channels
|
||||
import Phoenix.ChannelTest
|
||||
import App.ChannelCase
|
||||
|
||||
# The default endpoint for testing
|
||||
@endpoint App.Endpoint
|
||||
end
|
||||
end
|
||||
|
||||
setup tags do
|
||||
:ok = Ecto.Adapters.SQL.Sandbox.checkout(App.Repo)
|
||||
|
||||
unless tags[:async] do
|
||||
Ecto.Adapters.SQL.Sandbox.mode(App.Repo, {:shared, self()})
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
end
|
43
apps/app/test/support/conn_case.ex
Normal file
43
apps/app/test/support/conn_case.ex
Normal file
|
@ -0,0 +1,43 @@
|
|||
defmodule App.ConnCase do
|
||||
@moduledoc """
|
||||
This module defines the test case to be used by
|
||||
tests that require setting up a connection.
|
||||
|
||||
Such tests rely on `Phoenix.ConnTest` and also
|
||||
import other functionality to make it easier
|
||||
to build common data structures and query the data layer.
|
||||
|
||||
Finally, if the test case interacts with the database,
|
||||
we enable the SQL sandbox, so changes done to the database
|
||||
are reverted at the end of every test. If you are using
|
||||
PostgreSQL, you can even run database tests asynchronously
|
||||
by setting `use App.ConnCase, async: true`, although
|
||||
this option is not recommended for other databases.
|
||||
"""
|
||||
|
||||
use ExUnit.CaseTemplate
|
||||
|
||||
using do
|
||||
quote do
|
||||
# Import conveniences for testing with connections
|
||||
import Plug.Conn
|
||||
import Phoenix.ConnTest
|
||||
import App.ConnCase
|
||||
|
||||
alias App.Router.Helpers, as: Routes
|
||||
|
||||
# The default endpoint for testing
|
||||
@endpoint App.Endpoint
|
||||
end
|
||||
end
|
||||
|
||||
setup tags do
|
||||
:ok = Ecto.Adapters.SQL.Sandbox.checkout(App.Repo)
|
||||
|
||||
unless tags[:async] do
|
||||
Ecto.Adapters.SQL.Sandbox.mode(App.Repo, {:shared, self()})
|
||||
end
|
||||
|
||||
{:ok, conn: Phoenix.ConnTest.build_conn()}
|
||||
end
|
||||
end
|
2
apps/app/test/test_helper.exs
Normal file
2
apps/app/test/test_helper.exs
Normal file
|
@ -0,0 +1,2 @@
|
|||
ExUnit.start()
|
||||
Ecto.Adapters.SQL.Sandbox.mode(App.Repo, :manual)
|
32
apps/core/priv/templates/phx.gen.channel/channel.ex
Normal file
32
apps/core/priv/templates/phx.gen.channel/channel.ex
Normal file
|
@ -0,0 +1,32 @@
|
|||
defmodule <%= module %>Channel do
|
||||
use <%= web_module %>, :channel
|
||||
|
||||
@impl true
|
||||
def join("<%= singular %>:lobby", payload, socket) do
|
||||
if authorized?(payload) do
|
||||
{:ok, socket}
|
||||
else
|
||||
{:error, %{reason: "unauthorized"}}
|
||||
end
|
||||
end
|
||||
|
||||
# Channels can be used in a request/response fashion
|
||||
# by sending replies to requests from the client
|
||||
@impl true
|
||||
def handle_in("ping", payload, socket) do
|
||||
{:reply, {:ok, payload}, socket}
|
||||
end
|
||||
|
||||
# It is also common to receive messages from the client and
|
||||
# broadcast to everyone in the current topic (<%= singular %>:lobby).
|
||||
@impl true
|
||||
def handle_in("shout", payload, socket) do
|
||||
broadcast socket, "shout", payload
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
# Add authorization logic here as required.
|
||||
defp authorized?(_payload) do
|
||||
true
|
||||
end
|
||||
end
|
27
apps/core/priv/templates/phx.gen.channel/channel_test.exs
Normal file
27
apps/core/priv/templates/phx.gen.channel/channel_test.exs
Normal file
|
@ -0,0 +1,27 @@
|
|||
defmodule <%= module %>ChannelTest do
|
||||
use <%= web_module %>.ChannelCase
|
||||
|
||||
setup do
|
||||
{:ok, _, socket} =
|
||||
<%= web_module %>.UserSocket
|
||||
|> socket("user_id", %{some: :assign})
|
||||
|> subscribe_and_join(<%= module %>Channel, "<%= singular %>:lobby")
|
||||
|
||||
%{socket: socket}
|
||||
end
|
||||
|
||||
test "ping replies with status ok", %{socket: socket} do
|
||||
ref = push socket, "ping", %{"hello" => "there"}
|
||||
assert_reply ref, :ok, %{"hello" => "there"}
|
||||
end
|
||||
|
||||
test "shout broadcasts to <%= singular %>:lobby", %{socket: socket} do
|
||||
push socket, "shout", %{"hello" => "all"}
|
||||
assert_broadcast "shout", %{"hello" => "all"}
|
||||
end
|
||||
|
||||
test "broadcasts are pushed to the client", %{socket: socket} do
|
||||
broadcast_from! socket, "broadcast", %{"some" => "data"}
|
||||
assert_push "broadcast", %{"some" => "data"}
|
||||
end
|
||||
end
|
89
apps/core/priv/templates/phx.gen.context/access_no_schema.ex
Normal file
89
apps/core/priv/templates/phx.gen.context/access_no_schema.ex
Normal file
|
@ -0,0 +1,89 @@
|
|||
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
@doc """
|
||||
Returns the list of <%= schema.plural %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_<%= schema.plural %>()
|
||||
[%<%= inspect schema.alias %>{}, ...]
|
||||
|
||||
"""
|
||||
def list_<%= schema.plural %> do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single <%= schema.singular %>.
|
||||
|
||||
Raises if the <%= schema.human_singular %> does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_<%= schema.singular %>!(123)
|
||||
%<%= inspect schema.alias %>{}
|
||||
|
||||
"""
|
||||
def get_<%= schema.singular %>!(id), do: raise "TODO"
|
||||
|
||||
@doc """
|
||||
Creates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: bad_value})
|
||||
{:error, ...}
|
||||
|
||||
"""
|
||||
def create_<%= schema.singular %>(attrs \\ %{}) do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: new_value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: bad_value})
|
||||
{:error, ...}
|
||||
|
||||
"""
|
||||
def update_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a <%= inspect schema.alias %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:error, ...}
|
||||
|
||||
"""
|
||||
def delete_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>) do
|
||||
raise "TODO"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns a data structure for tracking <%= schema.singular %> changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
%Todo{...}
|
||||
|
||||
"""
|
||||
def change_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, _attrs \\ %{}) do
|
||||
raise "TODO"
|
||||
end
|
8
apps/core/priv/templates/phx.gen.context/context.ex
Normal file
8
apps/core/priv/templates/phx.gen.context/context.ex
Normal file
|
@ -0,0 +1,8 @@
|
|||
defmodule <%= inspect context.module %> do
|
||||
@moduledoc """
|
||||
The <%= context.name %> context.
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
alias <%= inspect schema.repo %>
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
defmodule <%= inspect context.module %>Test do
|
||||
use <%= inspect context.base_module %>.DataCase
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
end
|
11
apps/core/priv/templates/phx.gen.context/fixtures.ex
Normal file
11
apps/core/priv/templates/phx.gen.context/fixtures.ex
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
def <%= schema.singular %>_fixture(attrs \\ %{}) do
|
||||
{:ok, <%= schema.singular %>} =
|
||||
attrs
|
||||
|> Enum.into(%{
|
||||
<%= schema.params.create |> Enum.map(fn {key, val} -> " #{key}: #{inspect(val)}" end) |> Enum.join(",\n") %>
|
||||
})
|
||||
|> <%= inspect context.module %>.create_<%= schema.singular %>()
|
||||
|
||||
<%= schema.singular %>
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
defmodule <%= inspect context.module %>Fixtures do
|
||||
@moduledoc """
|
||||
This module defines test helpers for creating
|
||||
entities via the `<%= inspect context.module %>` context.
|
||||
"""
|
||||
end
|
96
apps/core/priv/templates/phx.gen.context/schema_access.ex
Normal file
96
apps/core/priv/templates/phx.gen.context/schema_access.ex
Normal file
|
@ -0,0 +1,96 @@
|
|||
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
@doc """
|
||||
Returns the list of <%= schema.plural %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_<%= schema.plural %>()
|
||||
[%<%= inspect schema.alias %>{}, ...]
|
||||
|
||||
"""
|
||||
def list_<%= schema.plural %> do
|
||||
Repo.all(<%= inspect schema.alias %>)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single <%= schema.singular %>.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the <%= schema.human_singular %> does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_<%= schema.singular %>!(123)
|
||||
%<%= inspect schema.alias %>{}
|
||||
|
||||
iex> get_<%= schema.singular %>!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_<%= schema.singular %>!(id), do: Repo.get!(<%= inspect schema.alias %>, id)
|
||||
|
||||
@doc """
|
||||
Creates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> create_<%= schema.singular %>(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_<%= schema.singular %>(attrs \\ %{}) do
|
||||
%<%= inspect schema.alias %>{}
|
||||
|> <%= inspect schema.alias %>.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: new_value})
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
|
||||
<%= schema.singular %>
|
||||
|> <%= inspect schema.alias %>.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a <%= schema.singular %>.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:ok, %<%= inspect schema.alias %>{}}
|
||||
|
||||
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>) do
|
||||
Repo.delete(<%= schema.singular %>)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking <%= schema.singular %> changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
%Ecto.Changeset{data: %<%= inspect schema.alias %>{}}
|
||||
|
||||
"""
|
||||
def change_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs \\ %{}) do
|
||||
<%= inspect schema.alias %>.changeset(<%= schema.singular %>, attrs)
|
||||
end
|
54
apps/core/priv/templates/phx.gen.context/test_cases.exs
Normal file
54
apps/core/priv/templates/phx.gen.context/test_cases.exs
Normal file
|
@ -0,0 +1,54 @@
|
|||
|
||||
describe "<%= schema.plural %>" do
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
import <%= inspect context.module %>Fixtures
|
||||
|
||||
@invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>
|
||||
|
||||
test "list_<%= schema.plural %>/0 returns all <%= schema.plural %>" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert <%= inspect context.alias %>.list_<%= schema.plural %>() == [<%= schema.singular %>]
|
||||
end
|
||||
|
||||
test "get_<%= schema.singular %>!/1 returns the <%= schema.singular %> with given id" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) == <%= schema.singular %>
|
||||
end
|
||||
|
||||
test "create_<%= schema.singular %>/1 with valid data creates a <%= schema.singular %>" do
|
||||
valid_attrs = <%= inspect schema.params.create %>
|
||||
|
||||
assert {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} = <%= inspect context.alias %>.create_<%= schema.singular %>(valid_attrs)<%= for {field, value} <- schema.params.create do %>
|
||||
assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
|
||||
end
|
||||
|
||||
test "create_<%= schema.singular %>/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.create_<%= schema.singular %>(@invalid_attrs)
|
||||
end
|
||||
|
||||
test "update_<%= schema.singular %>/2 with valid data updates the <%= schema.singular %>" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
update_attrs = <%= inspect schema.params.update %>
|
||||
|
||||
assert {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, update_attrs)<%= for {field, value} <- schema.params.update do %>
|
||||
assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
|
||||
end
|
||||
|
||||
test "update_<%= schema.singular %>/2 with invalid data returns error changeset" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, @invalid_attrs)
|
||||
assert <%= schema.singular %> == <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id)
|
||||
end
|
||||
|
||||
test "delete_<%= schema.singular %>/1 deletes the <%= schema.singular %>" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert {:ok, %<%= inspect schema.alias %>{}} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
assert_raise Ecto.NoResultsError, fn -> <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) end
|
||||
end
|
||||
|
||||
test "change_<%= schema.singular %>/1 returns a <%= schema.singular %> changeset" do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
assert %Ecto.Changeset{} = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
end
|
||||
end
|
16
apps/core/priv/templates/phx.gen.embedded/embedded_schema.ex
Normal file
16
apps/core/priv/templates/phx.gen.embedded/embedded_schema.ex
Normal file
|
@ -0,0 +1,16 @@
|
|||
defmodule <%= inspect schema.module %> do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
embedded_schema do
|
||||
<%= for {k, v} <- schema.types do %> field <%= inspect k %>, <%= inspect v %><%= schema.defaults[k] %>
|
||||
<% end %> end
|
||||
|
||||
@doc false
|
||||
def changeset(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
|
||||
<%= schema.singular %>
|
||||
|> cast(attrs, [<%= Enum.map_join(schema.attrs, ", ", &inspect(elem(&1, 0))) %>])
|
||||
|> validate_required([<%= Enum.map_join(schema.attrs, ", ", &inspect(elem(&1, 0))) %>])
|
||||
end
|
||||
end
|
62
apps/core/priv/templates/phx.gen.html/controller.ex
Normal file
62
apps/core/priv/templates/phx.gen.html/controller.ex
Normal file
|
@ -0,0 +1,62 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Controller do
|
||||
use <%= inspect context.web_module %>, :controller
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
def index(conn, _params) do
|
||||
<%= schema.plural %> = <%= inspect context.alias %>.list_<%= schema.plural %>()
|
||||
render(conn, "index.html", <%= schema.plural %>: <%= schema.plural %>)
|
||||
end
|
||||
|
||||
def new(conn, _params) do
|
||||
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(%<%= inspect schema.alias %>{})
|
||||
render(conn, "new.html", changeset: changeset)
|
||||
end
|
||||
|
||||
def create(conn, %{<%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
case <%= inspect context.alias %>.create_<%= schema.singular %>(<%= schema.singular %>_params) do
|
||||
{:ok, <%= schema.singular %>} ->
|
||||
conn
|
||||
|> put_flash(:info, "<%= schema.human_singular %> created successfully.")
|
||||
|> redirect(to: Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
render(conn, "new.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
render(conn, "show.html", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
|
||||
def edit(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
render(conn, "edit.html", <%= schema.singular %>: <%= schema.singular %>, changeset: changeset)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, <%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
|
||||
case <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, <%= schema.singular %>_params) do
|
||||
{:ok, <%= schema.singular %>} ->
|
||||
conn
|
||||
|> put_flash(:info, "<%= schema.human_singular %> updated successfully.")
|
||||
|> redirect(to: Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
render(conn, "edit.html", <%= schema.singular %>: <%= schema.singular %>, changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
{:ok, _<%= schema.singular %>} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
|
||||
|
||||
conn
|
||||
|> put_flash(:info, "<%= schema.human_singular %> deleted successfully.")
|
||||
|> redirect(to: Routes.<%= schema.route_helper %>_path(conn, :index))
|
||||
end
|
||||
end
|
84
apps/core/priv/templates/phx.gen.html/controller_test.exs
Normal file
84
apps/core/priv/templates/phx.gen.html/controller_test.exs
Normal file
|
@ -0,0 +1,84 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>ControllerTest do
|
||||
use <%= inspect context.web_module %>.ConnCase
|
||||
|
||||
import <%= inspect context.module %>Fixtures
|
||||
|
||||
@create_attrs <%= inspect schema.params.create %>
|
||||
@update_attrs <%= inspect schema.params.update %>
|
||||
@invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>
|
||||
|
||||
describe "index" do
|
||||
test "lists all <%= schema.plural %>", %{conn: conn} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :index))
|
||||
assert html_response(conn, 200) =~ "Listing <%= schema.human_plural %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "new <%= schema.singular %>" do
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :new))
|
||||
assert html_response(conn, 200) =~ "New <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create <%= schema.singular %>" do
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @create_attrs)
|
||||
|
||||
assert %{id: id} = redirected_params(conn)
|
||||
assert redirected_to(conn) == Routes.<%= schema.route_helper %>_path(conn, :show, id)
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, id))
|
||||
assert html_response(conn, 200) =~ "Show <%= schema.human_singular %>"
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @invalid_attrs)
|
||||
assert html_response(conn, 200) =~ "New <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "edit <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "renders form for editing chosen <%= schema.singular %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :edit, <%= schema.singular %>))
|
||||
assert html_response(conn, 200) =~ "Edit <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "update <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @update_attrs)
|
||||
assert redirected_to(conn) == Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>)
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))<%= if schema.string_attr do %>
|
||||
assert html_response(conn, 200) =~ <%= inspect Mix.Phoenix.Schema.default_param(schema, :update) %><% else %>
|
||||
assert html_response(conn, 200)<% end %>
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @invalid_attrs)
|
||||
assert html_response(conn, 200) =~ "Edit <%= schema.human_singular %>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "deletes chosen <%= schema.singular %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = delete(conn, Routes.<%= schema.route_helper %>_path(conn, :delete, <%= schema.singular %>))
|
||||
assert redirected_to(conn) == Routes.<%= schema.route_helper %>_path(conn, :index)
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp create_<%= schema.singular %>(_) do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
%{<%= schema.singular %>: <%= schema.singular %>}
|
||||
end
|
||||
end
|
5
apps/core/priv/templates/phx.gen.html/edit.html.eex
Normal file
5
apps/core/priv/templates/phx.gen.html/edit.html.eex
Normal file
|
@ -0,0 +1,5 @@
|
|||
<h1>Edit <%= schema.human_singular %></h1>
|
||||
|
||||
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :update, @<%= schema.singular %>)) %>
|
||||
|
||||
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index) %></span>
|
15
apps/core/priv/templates/phx.gen.html/form.html.eex
Normal file
15
apps/core/priv/templates/phx.gen.html/form.html.eex
Normal file
|
@ -0,0 +1,15 @@
|
|||
<%%= 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 %>
|
||||
<%= for {label, input, error} <- inputs, input do %>
|
||||
<%= label %>
|
||||
<%= input %>
|
||||
<%= error %>
|
||||
<% end %>
|
||||
<div>
|
||||
<%%= submit "Save" %>
|
||||
</div>
|
||||
<%% end %>
|
26
apps/core/priv/templates/phx.gen.html/index.html.eex
Normal file
26
apps/core/priv/templates/phx.gen.html/index.html.eex
Normal file
|
@ -0,0 +1,26 @@
|
|||
<h1>Listing <%= schema.human_plural %></h1>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<%= for {k, _} <- schema.attrs do %> <th><%= Phoenix.Naming.humanize(Atom.to_string(k)) %></th>
|
||||
<% end %>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%%= for <%= schema.singular %> <- @<%= schema.plural %> do %>
|
||||
<tr>
|
||||
<%= for {k, _} <- schema.attrs do %> <td><%%= <%= schema.singular %>.<%= k %> %></td>
|
||||
<% end %>
|
||||
<td>
|
||||
<span><%%= link "Show", to: Routes.<%= schema.route_helper %>_path(@conn, :show, <%= schema.singular %>) %></span>
|
||||
<span><%%= link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, <%= schema.singular %>) %></span>
|
||||
<span><%%= link "Delete", to: Routes.<%= schema.route_helper %>_path(@conn, :delete, <%= schema.singular %>), method: :delete, data: [confirm: "Are you sure?"] %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<%% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<span><%%= link "New <%= schema.human_singular %>", to: Routes.<%= schema.route_helper %>_path(@conn, :new) %></span>
|
5
apps/core/priv/templates/phx.gen.html/new.html.eex
Normal file
5
apps/core/priv/templates/phx.gen.html/new.html.eex
Normal file
|
@ -0,0 +1,5 @@
|
|||
<h1>New <%= schema.human_singular %></h1>
|
||||
|
||||
<%%= render "form.html", Map.put(assigns, :action, Routes.<%= schema.route_helper %>_path(@conn, :create)) %>
|
||||
|
||||
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index) %></span>
|
13
apps/core/priv/templates/phx.gen.html/show.html.eex
Normal file
13
apps/core/priv/templates/phx.gen.html/show.html.eex
Normal file
|
@ -0,0 +1,13 @@
|
|||
<h1>Show <%= schema.human_singular %></h1>
|
||||
|
||||
<ul>
|
||||
<%= for {k, _} <- schema.attrs do %>
|
||||
<li>
|
||||
<strong><%= Phoenix.Naming.humanize(Atom.to_string(k)) %>:</strong>
|
||||
<%%= @<%= schema.singular %>.<%= k %> %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<span><%%= link "Edit", to: Routes.<%= schema.route_helper %>_path(@conn, :edit, @<%= schema.singular %>) %></span>
|
||||
<span><%%= link "Back", to: Routes.<%= schema.route_helper %>_path(@conn, :index) %></span>
|
3
apps/core/priv/templates/phx.gen.html/view.ex
Normal file
3
apps/core/priv/templates/phx.gen.html/view.ex
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>View do
|
||||
use <%= inspect context.web_module %>, :view
|
||||
end
|
19
apps/core/priv/templates/phx.gen.json/changeset_view.ex
Normal file
19
apps/core/priv/templates/phx.gen.json/changeset_view.ex
Normal file
|
@ -0,0 +1,19 @@
|
|||
defmodule <%= inspect context.web_module %>.ChangesetView do
|
||||
use <%= inspect context.web_module %>, :view
|
||||
|
||||
@doc """
|
||||
Traverses and translates changeset errors.
|
||||
|
||||
See `Ecto.Changeset.traverse_errors/2` and
|
||||
`<%= inspect context.web_module %>.ErrorHelpers.translate_error/1` for more details.
|
||||
"""
|
||||
def translate_errors(changeset) do
|
||||
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
|
||||
end
|
||||
|
||||
def render("error.json", %{changeset: changeset}) do
|
||||
# When encoded, the changeset returns its errors
|
||||
# as a JSON object. So we just pass it forward.
|
||||
%{errors: translate_errors(changeset)}
|
||||
end
|
||||
end
|
43
apps/core/priv/templates/phx.gen.json/controller.ex
Normal file
43
apps/core/priv/templates/phx.gen.json/controller.ex
Normal file
|
@ -0,0 +1,43 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Controller do
|
||||
use <%= inspect context.web_module %>, :controller
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
action_fallback <%= inspect context.web_module %>.FallbackController
|
||||
|
||||
def index(conn, _params) do
|
||||
<%= schema.plural %> = <%= inspect context.alias %>.list_<%= schema.plural %>()
|
||||
render(conn, "index.json", <%= schema.plural %>: <%= schema.plural %>)
|
||||
end
|
||||
|
||||
def create(conn, %{<%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
with {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} <- <%= inspect context.alias %>.create_<%= schema.singular %>(<%= schema.singular %>_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
|> render("show.json", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
render(conn, "show.json", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, <%= inspect schema.singular %> => <%= schema.singular %>_params}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
|
||||
with {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} <- <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, <%= schema.singular %>_params) do
|
||||
render(conn, "show.json", <%= schema.singular %>: <%= schema.singular %>)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
<%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
|
||||
|
||||
with {:ok, %<%= inspect schema.alias %>{}} <- <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
84
apps/core/priv/templates/phx.gen.json/controller_test.exs
Normal file
84
apps/core/priv/templates/phx.gen.json/controller_test.exs
Normal file
|
@ -0,0 +1,84 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>ControllerTest do
|
||||
use <%= inspect context.web_module %>.ConnCase
|
||||
|
||||
import <%= inspect context.module %>Fixtures
|
||||
|
||||
alias <%= inspect schema.module %>
|
||||
|
||||
@create_attrs %{
|
||||
<%= schema.params.create |> Enum.map(fn {key, val} -> " #{key}: #{inspect(val)}" end) |> Enum.join(",\n") %>
|
||||
}
|
||||
@update_attrs %{
|
||||
<%= schema.params.update |> Enum.map(fn {key, val} -> " #{key}: #{inspect(val)}" end) |> Enum.join(",\n") %>
|
||||
}
|
||||
@invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>
|
||||
|
||||
setup %{conn: conn} do
|
||||
{:ok, conn: put_req_header(conn, "accept", "application/json")}
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
test "lists all <%= schema.plural %>", %{conn: conn} do
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :index))
|
||||
assert json_response(conn, 200)["data"] == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "create <%= schema.singular %>" do
|
||||
test "renders <%= schema.singular %> when data is valid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @create_attrs)
|
||||
assert %{"id" => id} = json_response(conn, 201)["data"]
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, id))
|
||||
|
||||
assert %{
|
||||
"id" => id<%= for {key, val} <- schema.params.create |> Phoenix.json_library().encode!() |> Phoenix.json_library().decode!() do %>,
|
||||
"<%= key %>" => <%= inspect(val) %><% end %>
|
||||
} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn} do
|
||||
conn = post(conn, Routes.<%= schema.route_helper %>_path(conn, :create), <%= schema.singular %>: @invalid_attrs)
|
||||
assert json_response(conn, 422)["errors"] != %{}
|
||||
end
|
||||
end
|
||||
|
||||
describe "update <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "renders <%= schema.singular %> when data is valid", %{conn: conn, <%= schema.singular %>: %<%= inspect schema.alias %>{id: id} = <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @update_attrs)
|
||||
assert %{"id" => ^id} = json_response(conn, 200)["data"]
|
||||
|
||||
conn = get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, id))
|
||||
|
||||
assert %{
|
||||
"id" => id<%= for {key, val} <- schema.params.update |> Phoenix.json_library().encode!() |> Phoenix.json_library().decode!() do %>,
|
||||
"<%= key %>" => <%= inspect(val) %><% end %>
|
||||
} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = put(conn, Routes.<%= schema.route_helper %>_path(conn, :update, <%= schema.singular %>), <%= schema.singular %>: @invalid_attrs)
|
||||
assert json_response(conn, 422)["errors"] != %{}
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete <%= schema.singular %>" do
|
||||
setup [:create_<%= schema.singular %>]
|
||||
|
||||
test "deletes chosen <%= schema.singular %>", %{conn: conn, <%= schema.singular %>: <%= schema.singular %>} do
|
||||
conn = delete(conn, Routes.<%= schema.route_helper %>_path(conn, :delete, <%= schema.singular %>))
|
||||
assert response(conn, 204)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, Routes.<%= schema.route_helper %>_path(conn, :show, <%= schema.singular %>))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp create_<%= schema.singular %>(_) do
|
||||
<%= schema.singular %> = <%= schema.singular %>_fixture()
|
||||
%{<%= schema.singular %>: <%= schema.singular %>}
|
||||
end
|
||||
end
|
24
apps/core/priv/templates/phx.gen.json/fallback_controller.ex
Normal file
24
apps/core/priv/templates/phx.gen.json/fallback_controller.ex
Normal file
|
@ -0,0 +1,24 @@
|
|||
defmodule <%= inspect context.web_module %>.FallbackController do
|
||||
@moduledoc """
|
||||
Translates controller action results into valid `Plug.Conn` responses.
|
||||
|
||||
See `Phoenix.Controller.action_fallback/1` for more details.
|
||||
"""
|
||||
use <%= inspect context.web_module %>, :controller
|
||||
|
||||
<%= if schema.generate? do %># This clause handles errors returned by Ecto's insert/update/delete.
|
||||
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> put_view(<%= inspect context.web_module %>.ChangesetView)
|
||||
|> render("error.json", changeset: changeset)
|
||||
end
|
||||
|
||||
<% end %># This clause is an example of how to handle resources that cannot be found.
|
||||
def call(conn, {:error, :not_found}) do
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> put_view(<%= inspect context.web_module %>.ErrorView)
|
||||
|> render(:"404")
|
||||
end
|
||||
end
|
17
apps/core/priv/templates/phx.gen.json/view.ex
Normal file
17
apps/core/priv/templates/phx.gen.json/view.ex
Normal file
|
@ -0,0 +1,17 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>View do
|
||||
use <%= inspect context.web_module %>, :view
|
||||
alias <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>View
|
||||
|
||||
def render("index.json", %{<%= schema.plural %>: <%= schema.plural %>}) do
|
||||
%{data: render_many(<%= schema.plural %>, <%= inspect schema.alias %>View, "<%= schema.singular %>.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{<%= schema.singular %>: <%= schema.singular %>}) do
|
||||
%{data: render_one(<%= schema.singular %>, <%= inspect schema.alias %>View, "<%= schema.singular %>.json")}
|
||||
end
|
||||
|
||||
def render("<%= schema.singular %>.json", %{<%= schema.singular %>: <%= schema.singular %>}) do
|
||||
%{id: <%= schema.singular %>.id<%= for {k, _} <- schema.attrs do %>,
|
||||
<%= k %>: <%= schema.singular %>.<%= k %><% end %>}
|
||||
end
|
||||
end
|
55
apps/core/priv/templates/phx.gen.live/form_component.ex
Normal file
55
apps/core/priv/templates/phx.gen.live/form_component.ex
Normal file
|
@ -0,0 +1,55 @@
|
|||
defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.FormComponent do
|
||||
use <%= inspect context.web_module %>, :live_component
|
||||
|
||||
alias <%= inspect context.module %>
|
||||
|
||||
@impl true
|
||||
def update(%{<%= schema.singular %>: <%= schema.singular %>} = assigns, socket) do
|
||||
changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(assigns)
|
||||
|> assign(:changeset, changeset)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("validate", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
|
||||
changeset =
|
||||
socket.assigns.<%= schema.singular %>
|
||||
|> <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>_params)
|
||||
|> Map.put(:action, :validate)
|
||||
|
||||
{:noreply, assign(socket, :changeset, changeset)}
|
||||
end
|
||||
|
||||
def handle_event("save", %{"<%= schema.singular %>" => <%= schema.singular %>_params}, socket) do
|
||||
save_<%= schema.singular %>(socket, socket.assigns.action, <%= schema.singular %>_params)
|
||||
end
|
||||
|
||||
defp save_<%= schema.singular %>(socket, :edit, <%= schema.singular %>_params) do
|
||||
case <%= inspect context.alias %>.update_<%= schema.singular %>(socket.assigns.<%= schema.singular %>, <%= schema.singular %>_params) do
|
||||
{:ok, _<%= schema.singular %>} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "<%= schema.human_singular %> updated successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, assign(socket, :changeset, changeset)}
|
||||
end
|
||||
end
|
||||
|
||||
defp save_<%= schema.singular %>(socket, :new, <%= schema.singular %>_params) do
|
||||
case <%= inspect context.alias %>.create_<%= schema.singular %>(<%= schema.singular %>_params) do
|
||||
{:ok, _<%= schema.singular %>} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "<%= schema.human_singular %> created successfully")
|
||||
|> push_redirect(to: socket.assigns.return_to)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, assign(socket, changeset: changeset)}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
<h2><%%= @title %></h2>
|
||||
|
||||
<%%= f = form_for @changeset, "#",
|
||||
id: "<%= schema.singular %>-form",
|
||||
phx_target: @myself,
|
||||
phx_change: "validate",
|
||||
phx_submit: "save" %>
|
||||
<%= for {label, input, error} <- inputs, input do %>
|
||||
<%= label %>
|
||||
<%= input %>
|
||||
<%= error %>
|
||||
<% end %>
|
||||
<%%= submit "Save", phx_disable_with: "Saving..." %>
|
||||
</form>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue