{"_id":"5777c96e5b2b430e00b982c0","project":"54348ec95b10711400c6c445","user":"5435e00ad7d8700800bbec51","category":{"_id":"5777c9635b2b430e00b982aa","version":"5777c9635b2b430e00b982a5","project":"54348ec95b10711400c6c445","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2014-12-03T21:36:49.014Z","from_sync":false,"order":4,"slug":"bonus-guides","title":"Bonus Guides"},"parentDoc":null,"__v":1,"version":{"_id":"5777c9635b2b430e00b982a5","__v":1,"project":"54348ec95b10711400c6c445","createdAt":"2016-07-02T14:02:11.084Z","releaseDate":"2016-07-02T14:02:11.084Z","categories":["5777c9635b2b430e00b982a6","5777c9635b2b430e00b982a7","5777c9635b2b430e00b982a8","5777c9635b2b430e00b982a9","5777c9635b2b430e00b982aa"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.2.0","version":"1.2.0"},"updates":["54b45a52f6445c1f00087526","555d3dc57e271d0d00f3cbc2","562840025cfea90d00ddc5f6","566a38991e08750d00a0c4a2","56743b7947f7010d005bffa6","569521342e5eb41700901a77","56a27e5e6928550d006c833f"],"next":{"pages":[],"description":""},"createdAt":"2014-12-03T22:18:52.548Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"never","params":[],"url":""},"isReference":false,"order":2,"body":"# Mix Tasks\n\nThere are currently a number of built-in Phoenix-specific and ecto-specific mix tasks available to us within a newly-generated application. We can also create our own application specific tasks.\n\n## Phoenix Specific Mix Tasks\n\n```console\n$ mix help | grep -i phoenix\nmix local.phoenix        # Updates Phoenix locally\nmix phoenix.digest       # Digests and compress static files\nmix phoenix.gen.channel  # Generates a Phoenix channel\nmix phoenix.gen.html     # Generates controller, model and views for an HTML based resource\nmix phoenix.gen.json     # Generates a controller and model for a JSON based resource\nmix phoenix.gen.model    # Generates an Ecto model\nmix phoenix.gen.presence # Generates a Presence tracker\nmix phoenix.gen.secret   # Generates a secret\nmix phoenix.new          # Creates a new Phoenix v1.2.1 application\nmix phoenix.routes       # Prints all routes\nmix phoenix.server       # Starts applications and their servers\n```\nWe have seen all of these at one point or another in the guides, but having all the information about them in one place seems like a good idea. And here we are.\n\n#### `mix phoenix.new`\n\nThis is how we tell Phoenix the framework to generate a new Phoenix application for us. We saw it early on in the [Up and Running Guide](http://www.phoenixframework.org/docs/up-and-running).\n\nBefore we begin, we should note that Phoenix uses [Ecto](https://github.com/elixir-lang/ecto) for database access and [Brunch.io](http://brunch.io/) for asset management by default. We can pass `--no-ecto` to opt out of Ecto and  `--no-brunch` to opt out of Brunch.io.\n\n> Note: If we do use Brunch.io, we need to install its dependencies before we start our application. `phoenix.new` will ask to do this for us. Otherwise, we can install them with `npm install`. If we don't install them, the app will throw errors and may not serve our assets properly.\n\nWe need to pass `phoenix.new` a name for our application. Conventionally, we use all lower-case letters with underscores.\n\n```console\n$ mix phoenix.new task_tester\n* creating task_tester/.gitignore\n. . .\n```\n\nWe can also use either a relative or absolute path.\n\nThis relative path works.\n\n```console\n$ mix phoenix.new ../task_tester\n* creating ../task_tester/.gitignore\n. . .\n```\n\nThis absolute path works as well.\n\n```console\n$ mix phoenix.new /Users/me/work/task_tester\n* creating /Users/me/work/task_tester/.gitignore\n. . .\n```\n\nThe `phoenix.new` task will also ask us if we want to install our dependencies. (Please see the note above about Brunch.io dependencies.)\n\n```console\nFetch and install dependencies? [Yn] y\n* running npm install && node node_modules/brunch/bin/brunch build\n* running mix deps.get\n```\n\nOnce all of our dependencies are installed, `phoenix.new` will tell us what our next steps are.\n\n```console\nWe are all set! Run your Phoenix application:\n\n$ cd task_tester\n$ mix phoenix.server\n\nYou can also run it inside IEx (Interactive Elixir) as:\n\n$ iex -S mix phoenix.server\n```\n\nBy default `phoenix.new` will assume we want to use ecto for our models. If we don't want to use ecto in our application, we can use the `--no-ecto` flag.\n\n```console\n$ mix phoenix.new task_tester --no-ecto\n* creating task_tester/.gitignore\n. . .\n```\n\nWith the `--no-ecto` flag, Phoenix will not make either ecto or postgrex a dependency of our application, and it will not create a `repo.ex` file.\n\nBy default, Phoenix will name our OTP application after the name we pass into `phoenix.new`. If we want, we can specify a different OTP application name with the `--app` flag.\n\n```console\n$  mix phoenix.new task_tester --app hello_phoenix\n* creating task_tester/config/config.exs\n* creating task_tester/config/dev.exs\n* creating task_tester/config/prod.exs\n* creating task_tester/config/prod.secret.exs\n* creating task_tester/config/test.exs\n* creating task_tester/lib/hello_phoenix.ex\n* creating task_tester/lib/hello_phoenix/endpoint.ex\n* creating task_tester/priv/static/robots.txt\n* creating task_tester/test/controllers/page_controller_test.exs\n* creating task_tester/test/views/error_view_test.exs\n* creating task_tester/test/views/page_view_test.exs\n* creating task_tester/test/support/conn_case.ex\n* creating task_tester/test/support/channel_case.ex\n* creating task_tester/test/test_helper.exs\n* creating task_tester/web/controllers/page_controller.ex\n* creating task_tester/web/templates/layout/app.html.eex\n* creating task_tester/web/templates/page/index.html.eex\n* creating task_tester/web/views/error_view.ex\n* creating task_tester/web/views/layout_view.ex\n* creating task_tester/web/views/page_view.ex\n* creating task_tester/web/router.ex\n* creating task_tester/web/web.ex\n* creating task_tester/mix.exs\n* creating task_tester/README.md\n* creating task_tester/lib/hello_phoenix/repo.ex\n. . .\n```\n\nIf we look in the resulting `mix.exs` file, we will see that our project app name is `hello_phoenix`.\n\n```elixir\ndefmodule HelloPhoenix.Mixfile do\n  use Mix.Project\n\n  def project do\n    [app: :hello_phoenix,\n    version: \"0.0.1\",\n. . .\n```\n\nA quick check will show that all of our module names are qualified with `HelloPhoenix`.\n\n```elixir\ndefmodule HelloPhoenix.PageController do\n  use HelloPhoenix.Web, :controller\n. . .\n```\n\nWe can also see that files related to the application as a whole - eg. files in `lib/` and the test seed file - have `hello_phoenix` in their names.\n\n```console\n* creating task_tester/lib/hello_phoenix.ex\n* creating task_tester/lib/hello_phoenix/endpoint.ex\n* creating task_tester/lib/hello_phoenix/repo.ex\n* creating task_tester/test/hello_phoenix_test.exs\n```\n\nIf we only want to change the qualifying prefix for module names, we can do that with the `--module` flag. It's important to note that the value of the `--module` must look like a valid module name with proper capitalization. The task will throw an error if it doesn't.\n\n```console\n$  mix phoenix.new task_tester --module HelloPhoenix\n* creating task_tester/config/config.exs\n* creating task_tester/config/dev.exs\n* creating task_tester/config/prod.exs\n* creating task_tester/config/prod.secret.exs\n* creating task_tester/config/test.exs\n* creating task_tester/lib/task_tester.ex\n* creating task_tester/lib/task_tester/endpoint.ex\n* creating task_tester/priv/static/robots.txt\n* creating task_tester/test/controllers/page_controller_test.exs\n* creating task_tester/test/views/error_view_test.exs\n* creating task_tester/test/views/page_view_test.exs\n* creating task_tester/test/support/conn_case.ex\n* creating task_tester/test/support/channel_case.ex\n* creating task_tester/test/test_helper.exs\n* creating task_tester/web/controllers/page_controller.ex\n* creating task_tester/web/templates/layout/app.html.eex\n* creating task_tester/web/templates/page/index.html.eex\n* creating task_tester/web/views/error_view.ex\n* creating task_tester/web/views/layout_view.ex\n* creating task_tester/web/views/page_view.ex\n* creating task_tester/web/router.ex\n* creating task_tester/web/web.ex\n* creating task_tester/mix.exs\n* creating task_tester/README.md\n* creating task_tester/lib/task_tester/repo.ex\n. . .\n```\n\nNotice that none of the files have `hello_phoenix` in their names. All filenames related to the application name are `task_tester`.\n\nIf we look at the project app name in `mix.exs`, we see that it is `task_tester`, but all the module qualifying names begin with `HelloPhoenix`.\n\n```elixir\ndefmodule HelloPhoenix.Mixfile do\n  use Mix.Project\n\n  def project do\n    [app: :task_tester,\n. . .\n```\n\n#### `mix phoenix.gen.html`\n\nPhoenix now offers the ability to generate all the code to stand up a complete HTML resource - ecto migration, ecto model, controller with all the necessary actions, view, and templates. This can be a tremendous timesaver. Let's take a look at how to make this happen.\n\nThe `phoenix.gen.html` task takes a number of arguments, the module name of the model, the resource name, and a list of column_name:type attributes. The module name we pass in must conform to the Elixir rules of module naming, following proper capitalization.\n\n```console\n$ mix phoenix.gen.html Post posts body:string word_count:integer\n* creating priv/repo/migrations/20150523120903_create_post.exs\n* creating web/models/post.ex\n* creating test/models/post_test.exs\n* creating web/controllers/post_controller.ex\n* creating web/templates/post/edit.html.eex\n* creating web/templates/post/form.html.eex\n* creating web/templates/post/index.html.eex\n* creating web/templates/post/new.html.eex\n* creating web/templates/post/show.html.eex\n* creating web/views/post_view.ex\n* creating test/controllers/post_controller_test.exs\n```\n\nWhen `phoenix.gen.html` is done creating files, it helpfully tells us that we need to add a line to our router file as well as run our ecto migrations.\n\n```console\nAdd the resource to your browser scope in web/router.ex:\n\n    resources \"/posts\", PostController\n\nand then update your repository by running migrations:\n\n$ mix ecto.migrate\n```\n\nImportant: If we don't do this, our application won't compile, and we'll get an error.\n\n```console\n$ mix phoenix.server\nCompiled web/models/post.ex\n\n== Compilation error on file web/controllers/post_controller.ex ==\n** (CompileError) web/controllers/post_controller.ex:27: function post_path/2 undefined\n(stdlib) lists.erl:1336: :lists.foreach/2\n(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6\n```\n\nIf we don't want to create a model for our resource we can use the `--no-model` flag.\n\n```console\n$ mix phoenix.gen.html Post posts body:string word_count:integer --no-model\n* creating web/controllers/post_controller.ex\n* creating web/templates/post/edit.html.eex\n* creating web/templates/post/form.html.eex\n* creating web/templates/post/index.html.eex\n* creating web/templates/post/new.html.eex\n* creating web/templates/post/show.html.eex\n* creating web/views/post_view.ex\n* creating test/controllers/post_controller_test.exs\n```\n\nIt will tell us we need to add a line to our router file, but since we skipped the model, it won't mention anything about `ecto.migrate`.\n\n```console\nAdd the resource to your browser scope in web/router.ex:\n\n    resources \"/posts\", PostController\n```\n\nImportant: If we don't do this, our application won't compile, and we'll get an error.\n\n```console\n$ mix phoenix.server\n\n== Compilation error on file web/views/post_view.ex ==\n** (CompileError) web/templates/post/edit.html.eex:4: function post_path/3 undefined\n    (stdlib) lists.erl:1336: :lists.foreach/2\n    (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6\n```\n\n#### `mix phoenix.gen.json`\n\nPhoenix also offers the ability to generate all the code to stand up a complete JSON resource - ecto migration, ecto model, controller with all the necessary actions and view. This command will not create any template for the app.\n\nThe `phoenix.gen.json` task takes a number of arguments, the module name of the model, the resource name, and a list of column_name:type attributes. The module name we pass in must conform to the Elixir rules of module naming, following proper capitalization.\n\n```console\n$ mix phoenix.gen.json Post posts title:string content:string\n* creating priv/repo/migrations/20150521140551_create_post.exs\n* creating web/models/post.ex\n* creating test/models/post_test.exs\n* creating web/controllers/post_controller.ex\n* creating web/views/post_view.ex\n* creating test/controllers/post_controller_test.exs\n* creating web/views/changeset_view.ex\n```\n\nWhen `phoenix.gen.json` is done creating files, it helpfully tells us that we need to add a line to our router file as well as run our ecto migrations.\n\n```console\nAdd the resource to your api scope in web/router.ex:\n\n    resources \"/posts\", PostController, except: [:new, :edit]\n\nand then update your repository by running migrations:\n\n    $ mix ecto.migrate\n```\n\nImportant: If we don't do this, our application won't compile, and we'll get an error.\n\n```console\n$ mix phoenix.server\nCompiled web/models/post.ex\n\n== Compilation error on file web/controllers/post_controller.ex ==\n** (CompileError) web/controllers/post_controller.ex:27: function post_path/2 undefined\n(stdlib) lists.erl:1336: :lists.foreach/2\n(stdlib) erl_eval.erl:657: :erl_eval.do_apply/6\n```\n\nIf we don't want to create a model for our resource we can use the `--no-model` flag.\n\n```console\n$ mix phoenix.gen.json Post posts title:string content:string --no-model\n* creating web/controllers/post_controller.ex\n* creating web/views/post_view.ex\n* creating test/controllers/post_controller_test.exs\n* creating web/views/changeset_view.ex\n```\n\nIt will tell us we need to add a line to our router file, but since we skipped the model, it won't mention anything about `ecto.migrate`.\n\n```console\nAdd the resource to your api scope in web/router.ex:\n\n    resources \"/posts\", PostController, except: [:new, :edit]\n```\n\nImportant: If we don't do this, our application won't compile, and we'll get an error.\n\n```console\n$ mix phoenix.server\n\n== Compilation error on file web/controllers/post_controller.ex ==\n** (CompileError) web/controllers/post_controller.ex:15: HelloPhoenix.Post.__struct__/0 is undefined, cannot expand struct HelloPhoenix.Post\n    (elixir) src/elixir_map.erl:55: :elixir_map.translate_struct/4\n    (stdlib) lists.erl:1352: :lists.mapfoldl/3\n```\n\n#### `mix phoenix.gen.model`\n\nIf we don't need a complete HTML/JSON resource and instead are only interested in a model, we can use the `phoenix.gen.model` task. It will generate a model, a migration and a test case.\n\nThe `phoenix.gen.model` task takes a number of arguments, the module name of the model, the plural model name used for the schema, and a list of column_name:type attributes.\n\n```console\n$ mix phoenix.gen.model User users name:string age:integer\n* creating priv/repo/migrations/20150527185323_create_user.exs\n* creating web/models/user.ex\n* creating test/models/user_test.exs\n```\n\n> Note: If we need to namespace our resource we can simply namespace the first argument of the generator.\n```console\n$ mix phoenix.gen.model Admin.User users name:string age:integer\n* creating priv/repo/migrations/20150527185940_create_admin_user.exs\n* creating web/models/admin/user.ex\n* creating test/models/admin/user_test.exs\n```\n\n#### `mix phoenix.gen.channel`\n\nThis task will generate a basic Phoenix channel as well a test case for it. It takes the module name for the channel as argument:\n\n```console\n$ mix phoenix.gen.channel Room\n* creating web/channels/room_channel.ex\n* creating test/channels/room_channel_test.exs\n```\n\nWhen `phoenix.gen.channel` is done, it helpfully tells us that we need to add a channel route to our router file.\n\n```console\nAdd the channel to your `web/channels/user_socket.ex` handler, for example:\n\n    channel \"rooms:lobby\", HelloPhoenix.RoomChannel\n```\n\n#### `mix phoenix.gen.presence`\n\nThis task will generate a Presence tracker. The module name can be passed as an argument, \n`Presence` is used if no module name is passed.\n\n```console\n$ mix phoenix.gen.presence Presence\n$ web/channels/presence.ex\n```\n\n#### `mix phoenix.routes`\n\nThis task has a single purpose, to show us all the routes defined for a given router. We saw it used extensively in the [Routing Guide](http://www.phoenixframework.org/docs/routing).\n\nIf we don't specify a router for this task, it will default to the router Phoenix generated for us.\n\n```console\n$ mix phoenix.routes\npage_path  GET  /  TaskTester.PageController.index/2\n```\nWe can also specify an individual router if we have more than one for our application.\n\n```console\n$ mix phoenix.routes TaskTester.Router\npage_path  GET  /  TaskTester.PageController.index/2\n```\n\n#### `mix phoenix.server`\n\nThis is the task we use to get our application running. It takes no arguments at all. If we pass any in, they will be silently ignored.\n\n```console\n$ mix phoenix.server\n[info] Running TaskTester.Endpoint with Cowboy on port 4000 (http)\n```\nIt silently ignores our `DoesNotExist` argument.\n\n```console\n$ mix phoenix.server DoesNotExist\n[info] Running TaskTester.Endpoint with Cowboy on port 4000 (http)\n```\nPrior to the 0.8.x versions of Phoenix, we used the `phoenix.start` task to get our applications running. That task no longer exists, and attempting to run it will cause an error.\n\n```console\n$ mix phoenix.start\n** (Mix) The task phoenix.start could not be found\n```\nIf we would like to start our application and also have an `iex` session open to it, we can run the mix task within `iex` like this, `iex -S mix phoenix.server`.\n\n```console\n$ iex -S mix phoenix.server\nErlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]\n\n[info] Running TaskTester.Endpoint with Cowboy on port 4000 (http)\nInteractive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help)\niex(1)>\n```\n\n#### `mix phoenix.digest`\n\nThis task does two things, it creates a digest for our static assets and then compresses them.\n\n\"Digest\" here refers to an MD5 digest of the contents of an asset which gets added to the filename of that asset. This creates a sort of \"fingerprint\" for it. If the digest doesn't change, browsers and CDNs will use a cached version. If it does change, they will re-fetch the new version.\n\nBefore we run this task let's inspect the contents of two directories in our hello_phoenix application.\n\nFirst `priv/static` which should look similar to this:\n\n```text\n├── images\n│   └── phoenix.png\n├── robots.txt\n```\n\nAnd then `web/static/` which should look similar to this:\n\n```text\n├── css\n│   └── app.css\n├── js\n│   └── app.js\n├── vendor\n│   └── phoenix.js\n```\n\nAll of these files are our static assets. Now let's run the `mix phoenix.digest` task.\n\n```console\n$ mix phoenix.digest\nCheck your digested files at 'priv/static'.\n```\n\nWe can now do as the task suggests and inspect the contents of `priv/static` directory. We'll see that all files from `web/static/` have been copied over to `priv/static` and also each file now has a couple of versions. Those versions are:\n\n* the original file\n* a compressed file with gzip\n* a file containing the original file name and its digest\n* a compressed file containing the file name and its digest\n\n> Note: We can specify a different output folder where `phoenix.digest` will put processed files. The first argument is the path where the static files are located.\n```console\n$ mix phoenix.digest priv/static -o www/public\nCheck your digested files at 'www/public'.\n```\n\n## Ecto Specific Mix Tasks\n\nNewly generated Phoenix applications now include ecto and postgrex as dependencies by default (which is to say, unless we use the `--no-ecto` flag with `phoenix.new`). With those dependencies come mix tasks to take care of common ecto operations. Let's see which tasks we get out of the box.\n\n```console\n$ mix help | grep -i ecto\nmix ecto.create          # Create the storage for the repo\nmix ecto.drop            # Drop the storage for the repo\nmix ecto.gen.migration   # Generate a new migration for the repo\nmix ecto.gen.repo        # Generates a new repository\nmix ecto.migrate         # Runs migrations up on a repo\nmix ecto.rollback        # Reverts migrations down on a repo\n```\n\nNote: We can run any of the tasks above with the `--no-start` flag to execute the task without starting the application.\n\n#### `ecto.create`\nThis task will create the database specified in our repo. By default it will look for the repo named after our application (the one generated with our app unless we opted out of ecto), but we can pass in another repo if we want.\n\nHere's what it looks like in action.\n\n```console\n$ mix ecto.create\nThe database for HelloPhoenix.Repo has been created.\n```\n\nIf we happen to have another repo called `OurCustom.Repo` that we want to create the database for, we can run this.\n\n```console\n$ mix ecto.create -r OurCustom.Repo\nThe database for OurCustom.Repo has been created.\n```\n\nThere are a few things that can go wrong with `ecto.create`. If our Postgres database doesn't have a \"postgres\" role (user), we'll get an error like this one.\n\n```console\n$ mix ecto.create\n** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: psql: FATAL:  role \"postgres\" does not exist\n```\n\nWe can fix this by creating the \"postgres\" role in the `psql` console  with the permissions needed to log in and create a database.\n\n```console\n=# CREATE ROLE postgres LOGIN CREATEDB;\nCREATE ROLE\n```\n\nIf the \"postgres\" role does not have permission to log in to the application, we'll get this error.\n\n```console\n$ mix ecto.create\n** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: psql: FATAL:  role \"postgres\" is not permitted to log in\n```\n\nTo fix this, we need to change the permissions on our \"postgres\" user to allow login.\n\n```console\n=# ALTER ROLE postgres LOGIN;\nALTER ROLE\n```\n\nIf the \"postgres\" role does not have permission to create a database, we'll get this error.\n\n```console\n$ mix ecto.create\n** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: ERROR:  permission denied to create database\n```\n\nTo fix this, we need to change the permissions on our \"postgres\" user in the `psql` console  to allow database creation.\n\n```console\n=# ALTER ROLE postgres CREATEDB;\nALTER ROLE\n```\n\nIf the \"postgres\" role is using a password different from the default \"postgres\", we'll get this error.\n\n```console\n$ mix ecto.create\n** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: psql: FATAL:  password authentication failed for user \"postgres\"\n```\n\nTo fix this, we can change the password in the environment specific configuration file. For the development environment the password used can be found at the bottom of the `config/dev.exs` file.\n\n#### `ecto.drop`\n\nThis task will drop the database specified in our repo. By default it will look for the repo named after our application (the one generated with our app unless we opted out of ecto). It will not prompt us to check if we're sure we want to drop the db, so do exercise caution.\n\n```console\n$ mix ecto.drop\nThe database for HelloPhoenix.Repo has been dropped.\n```\n\nIf we happen to have another repo that we want to drop the database for, we can specify it with the `-r` flag.\n\n```console\n$ mix ecto.drop -r OurCustom.Repo\nThe database for OurCustom.Repo has been dropped.\n```\n\n#### `ecto.gen.repo`\n\nMany applications require more than one data store. For each data store, we'll need a new repo, and we can generate them automatically with `ecto.gen.repo`.\n\nIf we name our repo `OurCustom.Repo`, this task will create it here `lib/our_custom/repo.ex`.\n\n```console\n$ mix ecto.gen.repo -r OurCustom.Repo\n* creating lib/our_custom\n* creating lib/our_custom/repo.ex\n* updating config/config.exs\nDon't forget to add your new repo to your supervision tree\n(typically in lib/hello_phoenix.ex):\n\nworker(OurCustom.Repo, [])\n```\n\nNotice that this task has updated `config/config.exs`. If we take a look, we'll see this extra configuration block for our new repo.\n\n```elixir\n. . .\nconfig :hello_phoenix, OurCustom.Repo,\nadapter: Ecto.Adapters.Postgres,\ndatabase: \"hello_phoenix_repo\",\nusername: \"user\",\npassword: \"pass\",\nhostname: \"localhost\"\n. . .\n```\n\nOf course, we'll need to change the login credentials to match what our database expects. We'll also need to change the config for other environments.\n\nWe certainly should follow the instructions and add our new repo to our supervision tree. In our `HelloPhoenix` application, we would open up `lib/hello_phoenix.ex`, and add our repo as a worker to the `children` list.\n\n```elixir\n. . .\nchildren = [\n  # Start the endpoint when the application starts\n  supervisor(HelloPhoenix.Endpoint, []),\n  # Start the Ecto repository\n  worker(HelloPhoenix.Repo, []),\n  # Here you could define other workers and supervisors as children\n  # worker(HelloPhoenix.Worker, [arg1, arg2, arg3]),\n  worker(OurCustom.Repo, []),\n]\n. . .\n```\n\n#### `ecto.gen.migration`\n\nMigrations are a programmatic, repeatable way to affect changes to a database schema. Migrations are also just modules, and we can create them with the `ecto.gen.migration` task. Let's walk through the steps to create a migration for a new comments table.\n\nWe simply need to invoke the task with a snake_case version of the module name that we want. Preferably, the name will describe what we want the migration to do.\n\n```console\nmix ecto.gen.migration add_comments_table\n* creating priv/repo/migrations\n* creating priv/repo/migrations/20150318001628_add_comments_table.exs\n```\n\nNotice that the migration's filename begins with a string representation of the date and time the file was created.\n\nLet's take a look at the file `ecto.gen.migration` has generated for us at `priv/repo/migrations/20150318001628_add_comments_table.exs`.\n\n```elixir\ndefmodule HelloPhoenix.Repo.Migrations.AddCommentsTable do\n  use Ecto.Migration\n\n  def change do\n  end\nend\n```\n\nNotice that there is a single function `change/0` which will handle both forward migrations and rollbacks. We'll define the schema changes that we want using ecto's handy dsl, and ecto will figure out what to do depending on whether we are rolling forward or rolling back. Very nice indeed.\n\nWhat we want to do is create a `comments` table with a `body` column, a `word_count` column, and timestamp columns for `inserted_at` and `updated_at`.\n\n```elixir\n. . .\ndef change do\n  create table(:comments) do\n    add :body,       :string\n    add :word_count, :integer\n    timestamps\n  end\nend\n. . .\n```\n\nAgain, we can run this task with the `-r` flag and another repo if we need to.\n\n```console\n$ mix ecto.gen.migration -r OurCustom.Repo add_users\n* creating priv/repo/migrations\n* creating priv/repo/migrations/20150318172927_add_users.exs\n```\n\nFor more infomation on ecto's migration dsl, please see the [ecto migration docs](http://hexdocs.pm/ecto/Ecto.Migration.html).\n\nThat's it! We're ready to run our migration.\n\n#### `ecto.migrate`\n\nOnce we have our migration module ready, we can simply run `mix ecto.migrate` to have our changes applied to the database.\n\n```console\n$ mix ecto.migrate\n[info] == Running HelloPhoenix.Repo.Migrations.AddCommentsTable.change/0 forward\n[info] create table comments\n[info] == Migrated in 0.1s\n```\n\nWhen we first run `ecto.migrate`, it will create a table for us called `schema_migrations`. This will keep track of all the migrations which we run by storing the timestamp portion of the migration's filename.\n\nHere's what the `schema_migrations` table looks like.\n\n```console\nhello_phoenix_dev=# select * from schema_migrations;\nversion     |     inserted_at\n----------------+---------------------\n20150317170448 | 2015-03-17 21:07:26\n20150318001628 | 2015-03-18 01:45:00\n(2 rows)\n```\n\nWhen we roll back a migration, `ecto.rollback` will remove the record representing this migration from `schema_migrations`.\n\nBy default, `ecto.migrate` will execute all pending migrations. We can exercise more control over which migrations we run by specifying some options when we run the task.\n\nWe can specify the number of pending migrations we would like to run with the `-n` or `--step` options.\n\n```console\n$ mix ecto.migrate -n 2\n[info] == Running HelloPhoenix.Repo.Migrations.CreatePost.change/0 forward\n[info] create table posts\n[info] == Migrated in 0.0s\n[info] == Running HelloPhoenix.Repo.Migrations.AddCommentsTable.change/0 forward\n[info] create table comments\n[info] == Migrated in 0.0s\n```\n\nThe `--step` option will behave the same way.\n\n```console\nmix ecto.migrate --step 2\n```\n\nWe can also specify an individual migration we would like to run with the `-v` option.\n\n```console\nmix ecto.migrate -v 20150317170448\n```\n\nThe `--to` option will behave the same way.\n\n```console\nmix ecto.migrate --to 20150317170448\n```\n\n#### `ecto.rollback`\n\nThe `ecto.rollback` task will reverse the last migration we have run, undoing the schema changes. `ecto.migrate` and `ecto.rollback` are mirror images of each other.\n\n```console\n$ mix ecto.rollback\n[info] == Running HelloPhoenix.Repo.Migrations.AddCommentsTable.change/0 backward\n[info] drop table comments\n[info] == Migrated in 0.0s\n```\n\n`ecto.rollback` will handle the same options as `ecto.migrate`, so `-n`, `--step`, `-v`, and `--to` will behave as they do for `ecto.migrate`.\n\n## Creating Our Own Mix Tasks\n\nAs we've seen throughout this guide, both mix itself and the dependencies we bring in to our application provide a number of really useful tasks for free. Since neither of these could possibly anticipate all our individual application's needs, mix allows us to create our own custom tasks. That's exactly what we are going to do now.\n\nThe first thing we need to do is create a `mix/tasks` directory inside of `lib`. This is where any of our application specific mix tasks will go.\n\n```console\n$ mkdir -p lib/mix/tasks\n```\n\nInside that directory, let's create a new file, `hello_phoenix.greeting.ex`, that looks like this.\n\n```elixir\ndefmodule Mix.Tasks.HelloPhoenix.Greeting do\n  use Mix.Task\n\n  :::at:::shortdoc \"Sends a greeting to us from Hello Phoenix\"\n\n  @moduledoc \"\"\"\n    This is where we would put any long form documentation or doctests.\n  \"\"\"\n\n  def run(_args) do\n    Mix.shell.info \"Greetings from the Hello Phoenix Application!\"\n  end\n\n  # We can define other functions as needed here.\nend\n```\n\nLet's take a quick look at the moving parts involved in a working mix task.\n\nThe first thing we need to do is name our module. In order to properly namespace it, we begin with `Mix.Tasks`. We'd like to invoke this as `mix hello_phoenix.greeting`, so we complete the module name with\n`HelloPhoenix.Greeting`.\n\nThe `use Mix.Task` line clearly brings in functionality from mix that makes this module behave as a mix task.\n\nThe `@shortdoc` module attribute holds a string which will describe our task when users invoke `mix help`.\n\n`@moduledoc` serves the same function that it does in any module. It's where we can put long-form documentation and doctests, if we have any.\n\nThe `run/1` function is the critical heart of any mix task. It's the function that does all the work when users invoke our task. In ours, all we do is send a greeting from our app, but we can implement our `run/1` function to do whatever we need it to. Note that `Mix.shell.info/1` is the preferred way to print text back out to the user.\n\nOf course, our task is just a module, so we can define other private functions as needed to support our `run/1` function.\n\nNow that we have our task module defined, our next step is to compile the application.\n\n```console\n$ mix compile\nCompiled lib/tasks/hello_phoenix.greeting.ex\nGenerated hello_phoenix.app\n```\n\nNow our new task should be visible to `mix help`.\n\n```console\n$ mix help | grep hello\nmix hello_phoenix.greeting # Sends a greeting to us from Hello Phoenix\n```\n\nNotice that `mix help` displays the text we put into the `@shortdoc` along with the name of our task.\n\nSo far, so good, but does it work?\n\n```console\n$ mix hello_phoenix.greeting\nGreetings from the Hello Phoenix Application!\n```\n\nIndeed it does.\n\nIf you want to make your new mix task to use your application's infrastructure, you need to make sure the application is started when mix task is being executed. This is particularly useful if you need to access your database from within the mix task. Thankfully, mix makes it really easy for us:\n\n```elixir\n  . . .\n  def run(_args) do\n    Mix.Task.run \"app.start\"\n    Mix.shell.info \"Now I have access to Repo and other goodies!\"\n  end\n  . . .\n```","excerpt":"","slug":"mix-tasks","type":"basic","title":"Mix Tasks"}
# Mix Tasks There are currently a number of built-in Phoenix-specific and ecto-specific mix tasks available to us within a newly-generated application. We can also create our own application specific tasks. ## Phoenix Specific Mix Tasks ```console $ mix help | grep -i phoenix mix local.phoenix # Updates Phoenix locally mix phoenix.digest # Digests and compress static files mix phoenix.gen.channel # Generates a Phoenix channel mix phoenix.gen.html # Generates controller, model and views for an HTML based resource mix phoenix.gen.json # Generates a controller and model for a JSON based resource mix phoenix.gen.model # Generates an Ecto model mix phoenix.gen.presence # Generates a Presence tracker mix phoenix.gen.secret # Generates a secret mix phoenix.new # Creates a new Phoenix v1.2.1 application mix phoenix.routes # Prints all routes mix phoenix.server # Starts applications and their servers ``` We have seen all of these at one point or another in the guides, but having all the information about them in one place seems like a good idea. And here we are. #### `mix phoenix.new` This is how we tell Phoenix the framework to generate a new Phoenix application for us. We saw it early on in the [Up and Running Guide](http://www.phoenixframework.org/docs/up-and-running). Before we begin, we should note that Phoenix uses [Ecto](https://github.com/elixir-lang/ecto) for database access and [Brunch.io](http://brunch.io/) for asset management by default. We can pass `--no-ecto` to opt out of Ecto and `--no-brunch` to opt out of Brunch.io. > Note: If we do use Brunch.io, we need to install its dependencies before we start our application. `phoenix.new` will ask to do this for us. Otherwise, we can install them with `npm install`. If we don't install them, the app will throw errors and may not serve our assets properly. We need to pass `phoenix.new` a name for our application. Conventionally, we use all lower-case letters with underscores. ```console $ mix phoenix.new task_tester * creating task_tester/.gitignore . . . ``` We can also use either a relative or absolute path. This relative path works. ```console $ mix phoenix.new ../task_tester * creating ../task_tester/.gitignore . . . ``` This absolute path works as well. ```console $ mix phoenix.new /Users/me/work/task_tester * creating /Users/me/work/task_tester/.gitignore . . . ``` The `phoenix.new` task will also ask us if we want to install our dependencies. (Please see the note above about Brunch.io dependencies.) ```console Fetch and install dependencies? [Yn] y * running npm install && node node_modules/brunch/bin/brunch build * running mix deps.get ``` Once all of our dependencies are installed, `phoenix.new` will tell us what our next steps are. ```console We are all set! Run your Phoenix application: $ cd task_tester $ mix phoenix.server You can also run it inside IEx (Interactive Elixir) as: $ iex -S mix phoenix.server ``` By default `phoenix.new` will assume we want to use ecto for our models. If we don't want to use ecto in our application, we can use the `--no-ecto` flag. ```console $ mix phoenix.new task_tester --no-ecto * creating task_tester/.gitignore . . . ``` With the `--no-ecto` flag, Phoenix will not make either ecto or postgrex a dependency of our application, and it will not create a `repo.ex` file. By default, Phoenix will name our OTP application after the name we pass into `phoenix.new`. If we want, we can specify a different OTP application name with the `--app` flag. ```console $ mix phoenix.new task_tester --app hello_phoenix * creating task_tester/config/config.exs * creating task_tester/config/dev.exs * creating task_tester/config/prod.exs * creating task_tester/config/prod.secret.exs * creating task_tester/config/test.exs * creating task_tester/lib/hello_phoenix.ex * creating task_tester/lib/hello_phoenix/endpoint.ex * creating task_tester/priv/static/robots.txt * creating task_tester/test/controllers/page_controller_test.exs * creating task_tester/test/views/error_view_test.exs * creating task_tester/test/views/page_view_test.exs * creating task_tester/test/support/conn_case.ex * creating task_tester/test/support/channel_case.ex * creating task_tester/test/test_helper.exs * creating task_tester/web/controllers/page_controller.ex * creating task_tester/web/templates/layout/app.html.eex * creating task_tester/web/templates/page/index.html.eex * creating task_tester/web/views/error_view.ex * creating task_tester/web/views/layout_view.ex * creating task_tester/web/views/page_view.ex * creating task_tester/web/router.ex * creating task_tester/web/web.ex * creating task_tester/mix.exs * creating task_tester/README.md * creating task_tester/lib/hello_phoenix/repo.ex . . . ``` If we look in the resulting `mix.exs` file, we will see that our project app name is `hello_phoenix`. ```elixir defmodule HelloPhoenix.Mixfile do use Mix.Project def project do [app: :hello_phoenix, version: "0.0.1", . . . ``` A quick check will show that all of our module names are qualified with `HelloPhoenix`. ```elixir defmodule HelloPhoenix.PageController do use HelloPhoenix.Web, :controller . . . ``` We can also see that files related to the application as a whole - eg. files in `lib/` and the test seed file - have `hello_phoenix` in their names. ```console * creating task_tester/lib/hello_phoenix.ex * creating task_tester/lib/hello_phoenix/endpoint.ex * creating task_tester/lib/hello_phoenix/repo.ex * creating task_tester/test/hello_phoenix_test.exs ``` If we only want to change the qualifying prefix for module names, we can do that with the `--module` flag. It's important to note that the value of the `--module` must look like a valid module name with proper capitalization. The task will throw an error if it doesn't. ```console $ mix phoenix.new task_tester --module HelloPhoenix * creating task_tester/config/config.exs * creating task_tester/config/dev.exs * creating task_tester/config/prod.exs * creating task_tester/config/prod.secret.exs * creating task_tester/config/test.exs * creating task_tester/lib/task_tester.ex * creating task_tester/lib/task_tester/endpoint.ex * creating task_tester/priv/static/robots.txt * creating task_tester/test/controllers/page_controller_test.exs * creating task_tester/test/views/error_view_test.exs * creating task_tester/test/views/page_view_test.exs * creating task_tester/test/support/conn_case.ex * creating task_tester/test/support/channel_case.ex * creating task_tester/test/test_helper.exs * creating task_tester/web/controllers/page_controller.ex * creating task_tester/web/templates/layout/app.html.eex * creating task_tester/web/templates/page/index.html.eex * creating task_tester/web/views/error_view.ex * creating task_tester/web/views/layout_view.ex * creating task_tester/web/views/page_view.ex * creating task_tester/web/router.ex * creating task_tester/web/web.ex * creating task_tester/mix.exs * creating task_tester/README.md * creating task_tester/lib/task_tester/repo.ex . . . ``` Notice that none of the files have `hello_phoenix` in their names. All filenames related to the application name are `task_tester`. If we look at the project app name in `mix.exs`, we see that it is `task_tester`, but all the module qualifying names begin with `HelloPhoenix`. ```elixir defmodule HelloPhoenix.Mixfile do use Mix.Project def project do [app: :task_tester, . . . ``` #### `mix phoenix.gen.html` Phoenix now offers the ability to generate all the code to stand up a complete HTML resource - ecto migration, ecto model, controller with all the necessary actions, view, and templates. This can be a tremendous timesaver. Let's take a look at how to make this happen. The `phoenix.gen.html` task takes a number of arguments, the module name of the model, the resource name, and a list of column_name:type attributes. The module name we pass in must conform to the Elixir rules of module naming, following proper capitalization. ```console $ mix phoenix.gen.html Post posts body:string word_count:integer * creating priv/repo/migrations/20150523120903_create_post.exs * creating web/models/post.ex * creating test/models/post_test.exs * creating web/controllers/post_controller.ex * creating web/templates/post/edit.html.eex * creating web/templates/post/form.html.eex * creating web/templates/post/index.html.eex * creating web/templates/post/new.html.eex * creating web/templates/post/show.html.eex * creating web/views/post_view.ex * creating test/controllers/post_controller_test.exs ``` When `phoenix.gen.html` is done creating files, it helpfully tells us that we need to add a line to our router file as well as run our ecto migrations. ```console Add the resource to your browser scope in web/router.ex: resources "/posts", PostController and then update your repository by running migrations: $ mix ecto.migrate ``` Important: If we don't do this, our application won't compile, and we'll get an error. ```console $ mix phoenix.server Compiled web/models/post.ex == Compilation error on file web/controllers/post_controller.ex == ** (CompileError) web/controllers/post_controller.ex:27: function post_path/2 undefined (stdlib) lists.erl:1336: :lists.foreach/2 (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6 ``` If we don't want to create a model for our resource we can use the `--no-model` flag. ```console $ mix phoenix.gen.html Post posts body:string word_count:integer --no-model * creating web/controllers/post_controller.ex * creating web/templates/post/edit.html.eex * creating web/templates/post/form.html.eex * creating web/templates/post/index.html.eex * creating web/templates/post/new.html.eex * creating web/templates/post/show.html.eex * creating web/views/post_view.ex * creating test/controllers/post_controller_test.exs ``` It will tell us we need to add a line to our router file, but since we skipped the model, it won't mention anything about `ecto.migrate`. ```console Add the resource to your browser scope in web/router.ex: resources "/posts", PostController ``` Important: If we don't do this, our application won't compile, and we'll get an error. ```console $ mix phoenix.server == Compilation error on file web/views/post_view.ex == ** (CompileError) web/templates/post/edit.html.eex:4: function post_path/3 undefined (stdlib) lists.erl:1336: :lists.foreach/2 (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6 ``` #### `mix phoenix.gen.json` Phoenix also offers the ability to generate all the code to stand up a complete JSON resource - ecto migration, ecto model, controller with all the necessary actions and view. This command will not create any template for the app. The `phoenix.gen.json` task takes a number of arguments, the module name of the model, the resource name, and a list of column_name:type attributes. The module name we pass in must conform to the Elixir rules of module naming, following proper capitalization. ```console $ mix phoenix.gen.json Post posts title:string content:string * creating priv/repo/migrations/20150521140551_create_post.exs * creating web/models/post.ex * creating test/models/post_test.exs * creating web/controllers/post_controller.ex * creating web/views/post_view.ex * creating test/controllers/post_controller_test.exs * creating web/views/changeset_view.ex ``` When `phoenix.gen.json` is done creating files, it helpfully tells us that we need to add a line to our router file as well as run our ecto migrations. ```console Add the resource to your api scope in web/router.ex: resources "/posts", PostController, except: [:new, :edit] and then update your repository by running migrations: $ mix ecto.migrate ``` Important: If we don't do this, our application won't compile, and we'll get an error. ```console $ mix phoenix.server Compiled web/models/post.ex == Compilation error on file web/controllers/post_controller.ex == ** (CompileError) web/controllers/post_controller.ex:27: function post_path/2 undefined (stdlib) lists.erl:1336: :lists.foreach/2 (stdlib) erl_eval.erl:657: :erl_eval.do_apply/6 ``` If we don't want to create a model for our resource we can use the `--no-model` flag. ```console $ mix phoenix.gen.json Post posts title:string content:string --no-model * creating web/controllers/post_controller.ex * creating web/views/post_view.ex * creating test/controllers/post_controller_test.exs * creating web/views/changeset_view.ex ``` It will tell us we need to add a line to our router file, but since we skipped the model, it won't mention anything about `ecto.migrate`. ```console Add the resource to your api scope in web/router.ex: resources "/posts", PostController, except: [:new, :edit] ``` Important: If we don't do this, our application won't compile, and we'll get an error. ```console $ mix phoenix.server == Compilation error on file web/controllers/post_controller.ex == ** (CompileError) web/controllers/post_controller.ex:15: HelloPhoenix.Post.__struct__/0 is undefined, cannot expand struct HelloPhoenix.Post (elixir) src/elixir_map.erl:55: :elixir_map.translate_struct/4 (stdlib) lists.erl:1352: :lists.mapfoldl/3 ``` #### `mix phoenix.gen.model` If we don't need a complete HTML/JSON resource and instead are only interested in a model, we can use the `phoenix.gen.model` task. It will generate a model, a migration and a test case. The `phoenix.gen.model` task takes a number of arguments, the module name of the model, the plural model name used for the schema, and a list of column_name:type attributes. ```console $ mix phoenix.gen.model User users name:string age:integer * creating priv/repo/migrations/20150527185323_create_user.exs * creating web/models/user.ex * creating test/models/user_test.exs ``` > Note: If we need to namespace our resource we can simply namespace the first argument of the generator. ```console $ mix phoenix.gen.model Admin.User users name:string age:integer * creating priv/repo/migrations/20150527185940_create_admin_user.exs * creating web/models/admin/user.ex * creating test/models/admin/user_test.exs ``` #### `mix phoenix.gen.channel` This task will generate a basic Phoenix channel as well a test case for it. It takes the module name for the channel as argument: ```console $ mix phoenix.gen.channel Room * creating web/channels/room_channel.ex * creating test/channels/room_channel_test.exs ``` When `phoenix.gen.channel` is done, it helpfully tells us that we need to add a channel route to our router file. ```console Add the channel to your `web/channels/user_socket.ex` handler, for example: channel "rooms:lobby", HelloPhoenix.RoomChannel ``` #### `mix phoenix.gen.presence` This task will generate a Presence tracker. The module name can be passed as an argument, `Presence` is used if no module name is passed. ```console $ mix phoenix.gen.presence Presence $ web/channels/presence.ex ``` #### `mix phoenix.routes` This task has a single purpose, to show us all the routes defined for a given router. We saw it used extensively in the [Routing Guide](http://www.phoenixframework.org/docs/routing). If we don't specify a router for this task, it will default to the router Phoenix generated for us. ```console $ mix phoenix.routes page_path GET / TaskTester.PageController.index/2 ``` We can also specify an individual router if we have more than one for our application. ```console $ mix phoenix.routes TaskTester.Router page_path GET / TaskTester.PageController.index/2 ``` #### `mix phoenix.server` This is the task we use to get our application running. It takes no arguments at all. If we pass any in, they will be silently ignored. ```console $ mix phoenix.server [info] Running TaskTester.Endpoint with Cowboy on port 4000 (http) ``` It silently ignores our `DoesNotExist` argument. ```console $ mix phoenix.server DoesNotExist [info] Running TaskTester.Endpoint with Cowboy on port 4000 (http) ``` Prior to the 0.8.x versions of Phoenix, we used the `phoenix.start` task to get our applications running. That task no longer exists, and attempting to run it will cause an error. ```console $ mix phoenix.start ** (Mix) The task phoenix.start could not be found ``` If we would like to start our application and also have an `iex` session open to it, we can run the mix task within `iex` like this, `iex -S mix phoenix.server`. ```console $ iex -S mix phoenix.server Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] [info] Running TaskTester.Endpoint with Cowboy on port 4000 (http) Interactive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> ``` #### `mix phoenix.digest` This task does two things, it creates a digest for our static assets and then compresses them. "Digest" here refers to an MD5 digest of the contents of an asset which gets added to the filename of that asset. This creates a sort of "fingerprint" for it. If the digest doesn't change, browsers and CDNs will use a cached version. If it does change, they will re-fetch the new version. Before we run this task let's inspect the contents of two directories in our hello_phoenix application. First `priv/static` which should look similar to this: ```text ├── images │ └── phoenix.png ├── robots.txt ``` And then `web/static/` which should look similar to this: ```text ├── css │ └── app.css ├── js │ └── app.js ├── vendor │ └── phoenix.js ``` All of these files are our static assets. Now let's run the `mix phoenix.digest` task. ```console $ mix phoenix.digest Check your digested files at 'priv/static'. ``` We can now do as the task suggests and inspect the contents of `priv/static` directory. We'll see that all files from `web/static/` have been copied over to `priv/static` and also each file now has a couple of versions. Those versions are: * the original file * a compressed file with gzip * a file containing the original file name and its digest * a compressed file containing the file name and its digest > Note: We can specify a different output folder where `phoenix.digest` will put processed files. The first argument is the path where the static files are located. ```console $ mix phoenix.digest priv/static -o www/public Check your digested files at 'www/public'. ``` ## Ecto Specific Mix Tasks Newly generated Phoenix applications now include ecto and postgrex as dependencies by default (which is to say, unless we use the `--no-ecto` flag with `phoenix.new`). With those dependencies come mix tasks to take care of common ecto operations. Let's see which tasks we get out of the box. ```console $ mix help | grep -i ecto mix ecto.create # Create the storage for the repo mix ecto.drop # Drop the storage for the repo mix ecto.gen.migration # Generate a new migration for the repo mix ecto.gen.repo # Generates a new repository mix ecto.migrate # Runs migrations up on a repo mix ecto.rollback # Reverts migrations down on a repo ``` Note: We can run any of the tasks above with the `--no-start` flag to execute the task without starting the application. #### `ecto.create` This task will create the database specified in our repo. By default it will look for the repo named after our application (the one generated with our app unless we opted out of ecto), but we can pass in another repo if we want. Here's what it looks like in action. ```console $ mix ecto.create The database for HelloPhoenix.Repo has been created. ``` If we happen to have another repo called `OurCustom.Repo` that we want to create the database for, we can run this. ```console $ mix ecto.create -r OurCustom.Repo The database for OurCustom.Repo has been created. ``` There are a few things that can go wrong with `ecto.create`. If our Postgres database doesn't have a "postgres" role (user), we'll get an error like this one. ```console $ mix ecto.create ** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: psql: FATAL: role "postgres" does not exist ``` We can fix this by creating the "postgres" role in the `psql` console with the permissions needed to log in and create a database. ```console =# CREATE ROLE postgres LOGIN CREATEDB; CREATE ROLE ``` If the "postgres" role does not have permission to log in to the application, we'll get this error. ```console $ mix ecto.create ** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: psql: FATAL: role "postgres" is not permitted to log in ``` To fix this, we need to change the permissions on our "postgres" user to allow login. ```console =# ALTER ROLE postgres LOGIN; ALTER ROLE ``` If the "postgres" role does not have permission to create a database, we'll get this error. ```console $ mix ecto.create ** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: ERROR: permission denied to create database ``` To fix this, we need to change the permissions on our "postgres" user in the `psql` console to allow database creation. ```console =# ALTER ROLE postgres CREATEDB; ALTER ROLE ``` If the "postgres" role is using a password different from the default "postgres", we'll get this error. ```console $ mix ecto.create ** (Mix) The database for HelloPhoenix.Repo couldn't be created, reason given: psql: FATAL: password authentication failed for user "postgres" ``` To fix this, we can change the password in the environment specific configuration file. For the development environment the password used can be found at the bottom of the `config/dev.exs` file. #### `ecto.drop` This task will drop the database specified in our repo. By default it will look for the repo named after our application (the one generated with our app unless we opted out of ecto). It will not prompt us to check if we're sure we want to drop the db, so do exercise caution. ```console $ mix ecto.drop The database for HelloPhoenix.Repo has been dropped. ``` If we happen to have another repo that we want to drop the database for, we can specify it with the `-r` flag. ```console $ mix ecto.drop -r OurCustom.Repo The database for OurCustom.Repo has been dropped. ``` #### `ecto.gen.repo` Many applications require more than one data store. For each data store, we'll need a new repo, and we can generate them automatically with `ecto.gen.repo`. If we name our repo `OurCustom.Repo`, this task will create it here `lib/our_custom/repo.ex`. ```console $ mix ecto.gen.repo -r OurCustom.Repo * creating lib/our_custom * creating lib/our_custom/repo.ex * updating config/config.exs Don't forget to add your new repo to your supervision tree (typically in lib/hello_phoenix.ex): worker(OurCustom.Repo, []) ``` Notice that this task has updated `config/config.exs`. If we take a look, we'll see this extra configuration block for our new repo. ```elixir . . . config :hello_phoenix, OurCustom.Repo, adapter: Ecto.Adapters.Postgres, database: "hello_phoenix_repo", username: "user", password: "pass", hostname: "localhost" . . . ``` Of course, we'll need to change the login credentials to match what our database expects. We'll also need to change the config for other environments. We certainly should follow the instructions and add our new repo to our supervision tree. In our `HelloPhoenix` application, we would open up `lib/hello_phoenix.ex`, and add our repo as a worker to the `children` list. ```elixir . . . children = [ # Start the endpoint when the application starts supervisor(HelloPhoenix.Endpoint, []), # Start the Ecto repository worker(HelloPhoenix.Repo, []), # Here you could define other workers and supervisors as children # worker(HelloPhoenix.Worker, [arg1, arg2, arg3]), worker(OurCustom.Repo, []), ] . . . ``` #### `ecto.gen.migration` Migrations are a programmatic, repeatable way to affect changes to a database schema. Migrations are also just modules, and we can create them with the `ecto.gen.migration` task. Let's walk through the steps to create a migration for a new comments table. We simply need to invoke the task with a snake_case version of the module name that we want. Preferably, the name will describe what we want the migration to do. ```console mix ecto.gen.migration add_comments_table * creating priv/repo/migrations * creating priv/repo/migrations/20150318001628_add_comments_table.exs ``` Notice that the migration's filename begins with a string representation of the date and time the file was created. Let's take a look at the file `ecto.gen.migration` has generated for us at `priv/repo/migrations/20150318001628_add_comments_table.exs`. ```elixir defmodule HelloPhoenix.Repo.Migrations.AddCommentsTable do use Ecto.Migration def change do end end ``` Notice that there is a single function `change/0` which will handle both forward migrations and rollbacks. We'll define the schema changes that we want using ecto's handy dsl, and ecto will figure out what to do depending on whether we are rolling forward or rolling back. Very nice indeed. What we want to do is create a `comments` table with a `body` column, a `word_count` column, and timestamp columns for `inserted_at` and `updated_at`. ```elixir . . . def change do create table(:comments) do add :body, :string add :word_count, :integer timestamps end end . . . ``` Again, we can run this task with the `-r` flag and another repo if we need to. ```console $ mix ecto.gen.migration -r OurCustom.Repo add_users * creating priv/repo/migrations * creating priv/repo/migrations/20150318172927_add_users.exs ``` For more infomation on ecto's migration dsl, please see the [ecto migration docs](http://hexdocs.pm/ecto/Ecto.Migration.html). That's it! We're ready to run our migration. #### `ecto.migrate` Once we have our migration module ready, we can simply run `mix ecto.migrate` to have our changes applied to the database. ```console $ mix ecto.migrate [info] == Running HelloPhoenix.Repo.Migrations.AddCommentsTable.change/0 forward [info] create table comments [info] == Migrated in 0.1s ``` When we first run `ecto.migrate`, it will create a table for us called `schema_migrations`. This will keep track of all the migrations which we run by storing the timestamp portion of the migration's filename. Here's what the `schema_migrations` table looks like. ```console hello_phoenix_dev=# select * from schema_migrations; version | inserted_at ----------------+--------------------- 20150317170448 | 2015-03-17 21:07:26 20150318001628 | 2015-03-18 01:45:00 (2 rows) ``` When we roll back a migration, `ecto.rollback` will remove the record representing this migration from `schema_migrations`. By default, `ecto.migrate` will execute all pending migrations. We can exercise more control over which migrations we run by specifying some options when we run the task. We can specify the number of pending migrations we would like to run with the `-n` or `--step` options. ```console $ mix ecto.migrate -n 2 [info] == Running HelloPhoenix.Repo.Migrations.CreatePost.change/0 forward [info] create table posts [info] == Migrated in 0.0s [info] == Running HelloPhoenix.Repo.Migrations.AddCommentsTable.change/0 forward [info] create table comments [info] == Migrated in 0.0s ``` The `--step` option will behave the same way. ```console mix ecto.migrate --step 2 ``` We can also specify an individual migration we would like to run with the `-v` option. ```console mix ecto.migrate -v 20150317170448 ``` The `--to` option will behave the same way. ```console mix ecto.migrate --to 20150317170448 ``` #### `ecto.rollback` The `ecto.rollback` task will reverse the last migration we have run, undoing the schema changes. `ecto.migrate` and `ecto.rollback` are mirror images of each other. ```console $ mix ecto.rollback [info] == Running HelloPhoenix.Repo.Migrations.AddCommentsTable.change/0 backward [info] drop table comments [info] == Migrated in 0.0s ``` `ecto.rollback` will handle the same options as `ecto.migrate`, so `-n`, `--step`, `-v`, and `--to` will behave as they do for `ecto.migrate`. ## Creating Our Own Mix Tasks As we've seen throughout this guide, both mix itself and the dependencies we bring in to our application provide a number of really useful tasks for free. Since neither of these could possibly anticipate all our individual application's needs, mix allows us to create our own custom tasks. That's exactly what we are going to do now. The first thing we need to do is create a `mix/tasks` directory inside of `lib`. This is where any of our application specific mix tasks will go. ```console $ mkdir -p lib/mix/tasks ``` Inside that directory, let's create a new file, `hello_phoenix.greeting.ex`, that looks like this. ```elixir defmodule Mix.Tasks.HelloPhoenix.Greeting do use Mix.Task @shortdoc "Sends a greeting to us from Hello Phoenix" @moduledoc """ This is where we would put any long form documentation or doctests. """ def run(_args) do Mix.shell.info "Greetings from the Hello Phoenix Application!" end # We can define other functions as needed here. end ``` Let's take a quick look at the moving parts involved in a working mix task. The first thing we need to do is name our module. In order to properly namespace it, we begin with `Mix.Tasks`. We'd like to invoke this as `mix hello_phoenix.greeting`, so we complete the module name with `HelloPhoenix.Greeting`. The `use Mix.Task` line clearly brings in functionality from mix that makes this module behave as a mix task. The `@shortdoc` module attribute holds a string which will describe our task when users invoke `mix help`. `@moduledoc` serves the same function that it does in any module. It's where we can put long-form documentation and doctests, if we have any. The `run/1` function is the critical heart of any mix task. It's the function that does all the work when users invoke our task. In ours, all we do is send a greeting from our app, but we can implement our `run/1` function to do whatever we need it to. Note that `Mix.shell.info/1` is the preferred way to print text back out to the user. Of course, our task is just a module, so we can define other private functions as needed to support our `run/1` function. Now that we have our task module defined, our next step is to compile the application. ```console $ mix compile Compiled lib/tasks/hello_phoenix.greeting.ex Generated hello_phoenix.app ``` Now our new task should be visible to `mix help`. ```console $ mix help | grep hello mix hello_phoenix.greeting # Sends a greeting to us from Hello Phoenix ``` Notice that `mix help` displays the text we put into the `@shortdoc` along with the name of our task. So far, so good, but does it work? ```console $ mix hello_phoenix.greeting Greetings from the Hello Phoenix Application! ``` Indeed it does. If you want to make your new mix task to use your application's infrastructure, you need to make sure the application is started when mix task is being executed. This is particularly useful if you need to access your database from within the mix task. Thankfully, mix makes it really easy for us: ```elixir . . . def run(_args) do Mix.Task.run "app.start" Mix.shell.info "Now I have access to Repo and other goodies!" end . . . ```