Current section
Files
Jump to
Current section
Files
lib/mix_tasks_phoenix_gen_controller.ex
defmodule Mix.Tasks.Phoenix.Gen.Controller do
use Mix.Task
import Mix.Generator
import Phoenix.Gen.Utils
@shortdoc "Generate a controller for a Phoenix Application"
@moduledoc """
Generates a Controller
mix phoenix.gen.controller resource_name action
## Command line options
* `--crud` - adds index, show, new, edit, create, update and delete actions
* `--repo` - repo to use with crud (defaults to 'YourApp.Repo')
* `--skip-view` - don't generate a view or any templates
* `--skip-route` - don't add the route for actions or --crud
## Examples
mix phoenix.gen.controller post recent --crud
"""
def run(opts) do
{switches, [resource_name | actions], _files} = OptionParser.parse opts
bindings = [
module: Module.concat(
app_name_camel, Mix.Utils.camelize(resource_name<>"Controller")),
actions: actions,
resource_name: resource_name,
crud: switches[:crud],
repo: switches[:repo] || Module.concat(app_name_camel, "Repo"),
model: Module.concat(app_name_camel, Mix.Utils.camelize(resource_name))
]
file = Path.join controllers_path, resource_name<>"_controller.ex"
create_file file, controller_template(bindings)
# generate the view file
unless Keyword.get switches, :skip_view do
Mix.Tasks.Phoenix.Gen.View.run [resource_name]
for action <- actions do
Mix.Tasks.Phoenix.Gen.Template.run [resource_name, action]
end
if switches[:crud] do
for action <- ~w|index show new edit _form _list| do
Mix.Tasks.Phoenix.Gen.Template.run [resource_name, action, "--crud"]
end
end
end
unless switches[:skip_route] do
if switches[:crud] do
add_resources_route resource_name
Mix.Shell.IO.info "A route was added for this resource."
end
for action <- actions do
add_action_route(resource_name, action)
Mix.Shell.IO.info "A route was added for #{resource_name}/#{action}"
end
end
end
defp add_action_route(resource_name, action) do
bindings = [
controller_path: resource_name,
action_path: (if action == "index", do: "", else: "/"<>action ),
action: action,
controller_name: Mix.Utils.camelize(resource_name)<>"Controller"
]
add_route action_route_template(bindings)
end
defp add_resources_route(resource_name) do
bindings = [
resources_name: Inflex.pluralize(resource_name),
controller_name: Mix.Utils.camelize(resource_name)<>"Controller"
]
add_route resources_route_template(bindings)
end
defp add_route(route) do
file = Path.join ~w|web router.ex|
contents = File.read! file
[_ | captures] = Regex.run(router_regex, contents)
contents = Enum.join captures, route
File.write! file, contents
end
defp router_regex do
~r/(.*pipe_through :browser(?(?!end).)*\n)(.*)/s
end
embed_template :controller, """
defmodule <%= inspect @module %> do
use Phoenix.Controller
plug :action
<%= if @crud do %>
@repo <%= inspect @repo %>
@model <%= inspect @model %>
@resource_path "<%= Inflex.pluralize @resource_name %>"
def index(conn, _params) do
render conn, :index, resources: @repo.all(@model)
end
def show(conn, params) do
render conn, :show, resource: @repo.get(@model, params["id"])
end
def new(conn, _params) do
render conn, :new, resource: @model.__struct__
end
def edit(conn, params) do
render conn, :edit, resource: @repo.get(@model, params["id"])
end
def create(conn, params) do
changeset = @model.changeset(@model.__struct__, params["resource"])
if changeset.valid? do
resource = @repo.insert(changeset)
render conn, :index, resources: @repo.all(@model)
else
render conn, :new, resource: Map.merge(@model.__struct__, params["resource"])
end
end
def update(conn, params) do
changeset = @model.changeset(@repo.get(@model, params["id"]), params["resource"])
if changeset.valid? do
resource = @repo.update(changeset)
render conn, :show, resource: resource
else
render conn, :new, resource: Map.merge(@repo.get(@model, params["id"]), params["resource"])
end
end
def delete(conn, params) do
resource = @repo.get(@model, params["id"])
@repo.delete resource
redirect conn, to: "/" <> @resource_path
end
<% end %>
<%= for action <- @actions do %>
def <%= action %>(conn, _params) do
render conn, :<%= action %>
end
<% end %>
end
"""
embed_template :resources_route, """
resources "/<%= @resources_name %>", <%= @controller_name %>
"""
embed_template :action_route, """
get "/<%= @controller_path %><%= @action_path %>", <%= @controller_name %>, :<%= @action %>
"""
end