Packages

A collection of boilerplate generators for the Phoenix web framework.

Current section

Files

Jump to
phoenix_generator lib mix_tasks_phoenix_gen_ectomodel.ex
Raw

lib/mix_tasks_phoenix_gen_ectomodel.ex

defmodule Mix.Tasks.Phoenix.Gen.Ectomodel do
use Mix.Task
import Phoenix.Gen.Utils
import Mix.Generator
import Mix.Shell.IO, only: [info: 1, error: 1]
@shortdoc "Generate an Ecto Model for a Phoenix Application"
@moduledoc """
Generates an Ecto Model
mix phoenix.gen.ectomodel model_name field_name:field_type
## Command line options
* `--timestamps` - adds inserted_at and updated_at to the model
* `--repo=RepoName` - the repo to generate a migration for (defaults to `YourApp.Repo`)
* `--skip-migration` - do not generate migration
## Examples
mix phoenix.gen.ectomodel user first_name:string age:integer --timestamps
"""
def run(opts) do
{switches, [model_name | fields], _files} = OptionParser.parse opts
timestamps = if switches[:timestamps], do: "timestamps", else: false
model_bindings = [
module: Module.concat(app_name_camel, Mix.Utils.camelize(model_name)),
schema_fields: fields |> parse_fields |> schema_fields,
changeset_fields: fields |> parse_fields |> changeset_fields(timestamps),
table_name: Inflex.pluralize(model_name),
timestamps: timestamps
]
model_path = Path.relative_to models_path, Mix.Project.app_path
model_file = Path.join model_path, "#{model_name}.ex"
create_file model_file, model_template(model_bindings)
unless switches[:skip_migration] do
repo = case switches[:repo] do
nil -> []
r -> ["-r", r]
end
Mix.Task.run("ecto.gen.migration", [migration_name(model_name)] ++ repo)
mig_bindings = Keyword.merge model_bindings, [
fields: fields |> parse_fields |> migration_fields,
]
#TODO make sure task was successful and we have the right file
mig_path = Path.relative_to migrations_path, Mix.Project.app_path
mig_file = Path.join mig_path, (mig_path |> File.ls! |> List.last)
mig = File.read! mig_file
mig = String.replace mig, ~r/def up do.* end/s, migration_template(mig_bindings)
File.write! mig_file, mig
info "Run your migration with: mix ecto.migrate #{Enum.join repo, " "}"
info "Warning: Migrations are poorly tested, please check before running!"
end
end
defp parse_fields(fields) do
for field <- fields, do: String.split(field, ":")
end
defp schema_fields(fields) do
for [field, type] <- fields, do: "field :#{field}, :#{type}"
end
defp migration_fields(fields) do
for [field, type] <- fields, do: "add :#{field}, :#{type}"
end
defp changeset_fields(fields, timestamps) do
for [field, type] <- fields, do: field
end
defp migration_name(model_name) do
"create_#{Inflex.pluralize model_name}_table"
end
embed_template :migration, """
def change do
create table(:<%= @table_name %>) do
<%= Enum.join @fields, "\n " %>
<%= @timestamps %>
end
end
"""
embed_template :model, """
defmodule <%= inspect @module %> do
use Ecto.Model
schema "<%= @table_name %>" do
<%= Enum.join @schema_fields, "\n " %>
<%= @timestamps %>
end
def changeset(resource, params) do
params
|> cast resource, [], <%= inspect @changeset_fields %>
end
end
"""
end