108 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
defmodule Mix.Tasks.Phx.Gen.Embedded do
 | 
						|
  @shortdoc "Generates an embedded Ecto schema file"
 | 
						|
 | 
						|
  @moduledoc """
 | 
						|
  Generates an embedded Ecto schema for casting/validating data outside the DB.
 | 
						|
 | 
						|
      mix phx.gen.embedded Blog.Post title:string views:integer
 | 
						|
 | 
						|
  The first argument is the schema module followed by the schema attributes.
 | 
						|
 | 
						|
  The generated schema above will contain:
 | 
						|
 | 
						|
    * an embedded schema file in `lib/my_app/blog/post.ex`
 | 
						|
 | 
						|
  ## Attributes
 | 
						|
 | 
						|
  The resource fields are given using `name:type` syntax
 | 
						|
  where type are the types supported by Ecto. Omitting
 | 
						|
  the type makes it default to `:string`:
 | 
						|
 | 
						|
      mix phx.gen.embedded Blog.Post title views:integer
 | 
						|
 | 
						|
  The following types are supported:
 | 
						|
 | 
						|
  #{for attr <- Mix.Phoenix.Schema.valid_types(), do: "  * `#{inspect attr}`\n"}
 | 
						|
    * `:datetime` - An alias for `:naive_datetime`
 | 
						|
  """
 | 
						|
  use Mix.Task
 | 
						|
 | 
						|
  alias Mix.Phoenix.Schema
 | 
						|
 | 
						|
  @switches [binary_id: :boolean, web: :string]
 | 
						|
 | 
						|
  @doc false
 | 
						|
  def run(args) do
 | 
						|
    if Mix.Project.umbrella?() do
 | 
						|
      Mix.raise "mix phx.gen.embedded must be invoked from within your *_web application root directory"
 | 
						|
    end
 | 
						|
 | 
						|
    schema = build(args)
 | 
						|
 | 
						|
    paths = Mix.Phoenix.generator_paths()
 | 
						|
 | 
						|
    prompt_for_conflicts(schema)
 | 
						|
 | 
						|
    copy_new_files(schema, paths, schema: schema)
 | 
						|
  end
 | 
						|
 | 
						|
  @doc false
 | 
						|
  def build(args) do
 | 
						|
    {schema_opts, parsed, _} = OptionParser.parse(args, switches: @switches)
 | 
						|
    [schema_name | attrs] = validate_args!(parsed)
 | 
						|
    opts =
 | 
						|
      schema_opts
 | 
						|
      |> Keyword.put(:embedded, true)
 | 
						|
      |> Keyword.put(:migration, false)
 | 
						|
 | 
						|
    schema = Schema.new(schema_name, nil, attrs, opts)
 | 
						|
 | 
						|
    schema
 | 
						|
  end
 | 
						|
 | 
						|
  @doc false
 | 
						|
  def validate_args!([schema | _] = args) do
 | 
						|
    if Schema.valid?(schema) do
 | 
						|
      args
 | 
						|
    else
 | 
						|
      raise_with_help "Expected the schema argument, #{inspect schema}, to be a valid module name"
 | 
						|
    end
 | 
						|
  end
 | 
						|
  def validate_args!(_) do
 | 
						|
    raise_with_help "Invalid arguments"
 | 
						|
  end
 | 
						|
 | 
						|
  @doc false
 | 
						|
  @spec raise_with_help(String.t) :: no_return()
 | 
						|
  def raise_with_help(msg) do
 | 
						|
    Mix.raise """
 | 
						|
    #{msg}
 | 
						|
 | 
						|
    mix phx.gen.embedded expects a module name followed by
 | 
						|
    any number of attributes:
 | 
						|
 | 
						|
        mix phx.gen.embedded Blog.Post title:string
 | 
						|
    """
 | 
						|
  end
 | 
						|
 | 
						|
 | 
						|
  defp prompt_for_conflicts(schema) do
 | 
						|
    schema
 | 
						|
    |> files_to_be_generated()
 | 
						|
    |> Mix.Phoenix.prompt_for_conflicts()
 | 
						|
  end
 | 
						|
 | 
						|
  @doc false
 | 
						|
  def files_to_be_generated(%Schema{} = schema) do
 | 
						|
    [{:eex, "embedded_schema.ex", schema.file}]
 | 
						|
  end
 | 
						|
 | 
						|
  @doc false
 | 
						|
  def copy_new_files(%Schema{} = schema, paths, binding) do
 | 
						|
    files = files_to_be_generated(schema)
 | 
						|
    Mix.Phoenix.copy_from(paths, "priv/templates/phx.gen.embedded", binding, files)
 | 
						|
 | 
						|
    schema
 | 
						|
  end
 | 
						|
end
 |