{"_id":"5777c9635b2b430e00b982b0","category":{"_id":"5777c9635b2b430e00b982a7","__v":0,"version":"5777c9635b2b430e00b982a5","project":"54348ec95b10711400c6c445","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2014-10-09T04:18:04.869Z","from_sync":false,"order":1,"slug":"guides","title":"Guides"},"parentDoc":null,"user":"5435e00ad7d8700800bbec51","project":"54348ec95b10711400c6c445","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"},"__v":0,"updates":["54820654c7026c210099d130","54871b21a8b5e31600952cfa","54872074a8b5e31600952d08","5487231cb3441a1f00f20d97","5487ee9dc178b40b00aa2eb4","5488d8f3f291f61400c02d0a","548bccda980a200b002c3307","54b539883157eb2a0053c6c8","54be86c2ffb79c320030dab6","54c422295622110d0003d37b","54de6b7f8e7b000d007c7edd","54e609b3dca0301700114209","54e60a937b1c272b00bb0d3a","54fe80cb4f692335008c35a9","54ff1732ea045523005758e2","54ff7b752882a10d0054696e","5553a255d402b92300cee38f","5554e12c15a70e230001548c","557ed51aeb75d80d00af3f60","558e82628efbc30d00fbc088","559df406cfd6260d003c3c64","55afaa34c8a85321007a541f","560301001ba3720d00a6bb05","561aac2713874c0d0070397f","5643527c0d9748190079dea4","564f97c6eb5bd10d009d7fa9","5658672ec4744f0d008a2608","569602610c650a23002506cc","56972a548560a60d00e2c245","56e901bbc88bf80e00f8bf34","5728cbc7b599290e00dbaae6","5728fc560388c70e00f3d884"],"next":{"pages":[],"description":""},"createdAt":"2014-12-03T22:02:22.142Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"never","params":[],"url":""},"isReference":false,"order":1,"body":"Our task for this guide is to add two new pages to our Phoenix application. One will be a purely static page, and the other will take part of the path from the URL as input and pass it through to a template for display. Along the way, we will gain familiarity with the basic components of a Phoenix application: the router, controllers, views, and templates.\n\nWhen Phoenix generates a new application for us, it builds a top-level directory structure like this:\n\n```text\n├── _build\n├── config\n├── deps\n├── lib\n├── priv\n├── test\n├── web\n```\n\nMost of our work in this guide will be in the `web` directory, which looks like this when expanded:\n\n```text\n├── channels\n    └── user_socket.ex\n├── controllers\n│   └── page_controller.ex\n├── models\n├── static\n│   ├── assets\n│   |   ├── images\n|   |   |   └── phoenix.png\n|   |   └── favicon.ico\n|   |   └── robots.txt\n│   |   ├── vendor\n├── templates\n│   ├── layout\n│   │   └── app.html.eex\n│   └── page\n│       └── index.html.eex\n└── views\n|   ├── error_helpers.ex\n|   ├── error_view.ex\n|   ├── layout_view.ex\n|   └── page_view.ex\n├── router.ex\n├── gettext.ex\n├── web.ex\n```\n\nAll of the files which are currently in the `controllers`, `templates`, and `views` directories are there to create the \"Welcome to Phoenix!\" page we saw in the last guide. We will see how we can re-use some of that code shortly. By convention, in the development environment, anything in the `web` directory will be automatically recompiled when there is a new web request.\n\nAll of our application's static assets live in `priv/static` in the directory appropriate for each type of file - css, images or js. We place assets that require a build phase into `web/static`, and the source files are built into their respective `app.js` / `app.css` bundles within `priv/static`. We won't be making any changes here for now, but it is good to know where to look for future reference.\n\n```text\npriv\n└── static\n    └── images\n        └── phoenix.png\n```\n\n```text\nweb\n└── static\n    ├── assets\n    |   ├── css\n    |   |   └── app.css\n    |   ├── js\n    |   │   └── app.js\n    |   └── vendor\n```\n\nThe `lib` directory also contains files we should know about. Our application's endpoint is at `lib/hello_phoenix/endpoint.ex`, and our application file (which starts our application and its supervision tree) is at `lib/hello_phoenix.ex`.\n\n```text\nlib\n├── hello_phoenix\n|   ├── endpoint.ex\n│   └── repo.ex\n└── hello_phoenix.ex\n```\n\nUnlike the `web` directory, Phoenix won't recompile files inside of `lib` when there is a new web request. This is intentional! The distinction between `web` and `lib` provides a convention for the different ways that we handle state inside of our application. The `web` directory contains anything whose state lasts for the duration of a web request. The `lib` directory contains both shared modules and anything that needs to manage state outside of the duration of a web request.\n\nEnough prep, let's get on with our first new Phoenix page!\n\n### A New Route\n\nRoutes map unique HTTP verb/path pairs to controller/action pairs which will handle them. Phoenix generates a router file for us in new applications at `web/router.ex`. This is where we will be working for this section.\n\nThe route for our \"Welcome to Phoenix!\" page from the previous Up And Running Guide looks like this.\n\n```elixir\nget \"/\", PageController, :index\n```\n\nLet's digest what this route is telling us. Visiting [http://localhost:4000/](http://localhost:4000/) issues an HTTP `GET` request to the root path. All requests like this will be handled by the `index` function in the `HelloPhoenix.PageController` module defined in `web/controllers/page_controller.ex`.\n\nThe page we are going to build will simply say \"Hello World, from Phoenix!\" when we point our browser to [http://localhost:4000/hello](http://localhost:4000/hello).\n\nThe first thing we need to do to create that page is define a route for it. Let's open up `web/router.ex` in a text editor. It should currently look like this:\n\n```elixir\ndefmodule HelloPhoenix.Router do\n  use HelloPhoenix.Web, :router\n\n  pipeline :browser do\n    plug :accepts, [\"html\"]\n    plug :fetch_session\n    plug :fetch_flash\n    plug :protect_from_forgery\n    plug :put_secure_browser_headers\n  end\n\n  pipeline :api do\n    plug :accepts, [\"json\"]\n  end\n\n  scope \"/\", HelloPhoenix do\n    pipe_through :browser # Use the default browser stack\n\n    get \"/\", PageController, :index\n  end\n\n  # Other scopes may use custom stacks.\n  # scope \"/api\", HelloPhoenix do\n  #   pipe_through :api\n  # end\nend\n\n```\n\nFor now, we'll ignore the pipelines and the use of `scope` here and just focus on adding a route. (We cover these topics in the [Routing Guide](http://www.phoenixframework.org/docs/routing), if you're curious.)\n\nLet's add a new route to the router that maps a `GET` request for `/hello` to the `index` action of a soon-to-be-created `HelloPhoenix.HelloController`:\n\n```elixir\nget \"/hello\", HelloController, :index\n```\n\nThe `scope \"/\"` block of our `router.ex` file should now look like this:\n\n```elixir\nscope \"/\", HelloPhoenix do\n  pipe_through :browser # Use the default browser stack\n\n  get \"/\", PageController, :index\n  get \"/hello\", HelloController, :index\nend\n```\n\n### A New Controller\n\nControllers are Elixir modules, and actions are Elixir functions defined in them. The purpose of actions is to gather any data and perform any tasks needed for rendering. Our route specifies that we need a `HelloPhoenix.HelloController` module with an `index/2` action.\n\nTo make that happen, let's create a new `web/controllers/hello_controller.ex` file, and make it look like the following:\n\n```elixir\ndefmodule HelloPhoenix.HelloController do\n  use HelloPhoenix.Web, :controller\n\n  def index(conn, _params) do\n    render conn, \"index.html\"\n  end\nend\n```\nWe'll save a discussion of `use HelloPhoenix.Web, :controller` for the [Controllers Guide](http://www.phoenixframework.org/docs/controllers). For now, let's focus on the `index/2` action.\n\nAll controller actions take two arguments. The first is `conn`, a struct which holds a ton of data about the request. The second is `params`, which are the request parameters. Here, we are not using `params`, and we avoid compiler warnings by adding the leading `_`.\n\nThe core of this action is `render conn, \"index.html\"`. This tells Phoenix to find a template called `index.html.eex` and render it. Phoenix will look for the template in a directory named after our controller, so `web/templates/hello`.\n\n> Note: Using an atom as the template name will also work here, `render conn, :index`, but the template will be chosen based off the Accept headers, e.g. `\"index.html\"` or `\"index.json\"`.\n\nThe modules responsible for rendering are views, and we'll make a new one of those next.\n\n### A New View\n\nPhoenix views have several important jobs. They render templates. They also act as a presentation layer for raw data from the controller, preparing it for use in a template. Functions which perform this transformation should go in a view.\n\nAs an example, say we have a data structure which represents a user with a `first_name` field and a `last_name` field, and in a template, we want to show the user's full name. We could write code in the template to merge those fields into a full name, but the better approach is to write a function in the view to do it for us, then call that function in the template. The result is a cleaner and more legible template.\n\nIn order to render any templates for our `HelloController`, we need a `HelloView`. The names are significant here - the first part of the names of the view and controller must match. Let's create an empty one for now, and leave a more detailed description of views for later. Create `web/views/hello_view.ex` and make it look like this:\n\n```elixir\ndefmodule HelloPhoenix.HelloView do\n  use HelloPhoenix.Web, :view\nend\n```\n\n### A New Template\n\nPhoenix templates are just that, templates into which data can be rendered. The standard templating engine Phoenix uses is EEx, which stands for [Embedded Elixir](http://elixir-lang.org/docs/stable/eex/). All of our template files will have the `.eex` file extension.\n\nTemplates are scoped to a view, which are scoped to controller. Phoenix creates a `web/templates` directory where we can put all these. It is best to namespace these for organization, so for our hello page, that means we need to create a `hello` directory under `web/templates` and then create an `index.html.eex` file within it.\n\nLet's do that now. Create `web/templates/hello/index.html.eex` and make it look like this:\n\n```html\n<div class=\"jumbotron\">\n  <h2>Hello World, from Phoenix!</h2>\n</div>\n```\n\nNow that we've got the route, controller, view, and template, we should be able to point our browsers at [http://localhost:4000/hello](http://localhost:4000/hello) and see our greeting from Phoenix! (In case you stopped the server along the way, the task to restart it is `mix phoenix.server`.)\n\n![Phoenix Greets Us](/images/hello-from-phoenix.png)\n\nThere are a couple of interesting things to notice about what we just did. We didn't need to stop and re-start the server while we made these changes. Yes, Phoenix has hot code reloading! Also, even though our `index.html.eex` file consisted of only a single `div` tag, the page we get is a full HTML document. Our index template is rendered into the application layout - `web/templates/layout/app.html.eex`. If you open it, you'll see a line that looks like this:\n\n    <%= render :::at:::view_module, @view_template, assigns %>\n\nwhich is what renders our template into the layout before the HTML is sent off to the browser.\n\n## Another New Page\n\nLet's add just a little complexity to our application. We're going to add a new page that will recognize a piece of the URL, label it as a \"messenger\" and pass it through the controller into the template so our messenger can say hello.\n\nAs we did last time, the first thing we'll do is create a new route.\n\n### A New Route\n\nFor this exercise, we're going to re-use the `HelloController` we just created and just add a new `show` action. We'll add a line just below our last route, like this:\n\n```elixir\nscope \"/\", HelloPhoenix do\n  pipe_through :browser # Use the default browser stack.\n\n  get \"/\", PageController, :index\n  get \"/hello\", HelloController, :index\n  get \"/hello/:messenger\", HelloController, :show\nend\n```\nNotice that we put the atom `:messenger` in the path. Phoenix will take whatever value that appears in that position in the URL and pass a [Map](http://elixir-lang.org/docs/stable/elixir/Map.html) with the key `messenger` pointing to that value to the controller.\n\nFor example, if we point the browser at: [http://localhost:4000/hello/Frank](http://localhost:4000/hello/Frank), the value of \":messenger\" will be \"Frank\".\n\n### A New Action\n\nRequests to our new route will be handled by the `HelloPhoenix.HelloController` `show` action. We already have the controller at `web/controllers/hello_controller.ex`, so all we need to do is edit that file and add a `show` action to it. This time, we'll need to keep one of the items in the map of params that gets passed into the action, so that we can pass it (the messenger) to the template. To do that, we add this show function to the controller:\n\n```elixir\ndef show(conn, %{\"messenger\" => messenger}) do\n  render conn, \"show.html\", messenger: messenger\nend\n```\n\nThere are a couple of things to notice here. We pattern match against the params passed into the show function so that the `messenger` variable will be bound to the value we put in the `:messenger` position in the URL. For example, if our URL is [http://localhost:4000/hello/Frank](http://localhost:4000/hello/Frank), the messenger variable would be bound to `Frank`.\n\nWithin the body of the `show` action, we also pass a third argument into the render function, a key/value pair where `:messenger` is the key, and the `messenger` variable is passed as the value.\n\n> Note: If the body of the action needs access to the full map of parameters bound to the params variable in addition to the bound messenger variable, we could define `show/2` like this:\n\n```elixir\ndef show(conn, %{\"messenger\" => messenger} = params) do\n  ...\nend\n```\n\nIt's good to remember that the keys to the `params` map will always be strings, and that the equals sign does not represent assignment, but is instead a [pattern match](http://elixir-lang.org/getting-started/pattern-matching.html) assertion.\n\n### A New Template\n\nFor the last piece of this puzzle, we'll need a new template. Since it is for the `show` action of the `HelloController`, it will go into the `web/templates/hello` directory and be called `show.html.eex`. It will look surprisingly like our `index.html.eex` template, except that we will need to display the name of our messenger.\n\nTo do that, we'll use the special EEx tags for executing Elixir expressions - `<%=  %>`. Notice that the initial tag has an equals sign like this: `<%=` . That means that any Elixir code that goes between those tags will be executed, and the resulting value will replace the tag. If the equals sign were missing, the code would still be executed, but the value would not appear on the page.\n\nAnd this is what the template should look like:\n\n```html\n<div class=\"jumbotron\">\n  <h2>Hello World, from <%= @messenger %>!</h2>\n</div>\n```\n\nOur messenger appears as `@messenger`. In this case, this is not a module attribute. It is special bit of metaprogrammed syntax which stands in for `Map.get(assigns, :messenger)`. The result is much nicer on the eyes and much easier to work with in a template.\n\nWe're done. If you point your browser here: [http://localhost:4000/hello/Frank](http://localhost:4000/hello/Frank), you should see a page that looks like this:\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/tXWKhaWATbuiAnIZLplM_hello-from-phoenix.png\",\n        \"hello-from-phoenix.png\",\n        \"1602\",\n        \"886\",\n        \"#603129\",\n        \"\"\n      ],\n      \"caption\": \"Hello World, from Phoenix!\"\n    }\n  ]\n}\n[/block]\nPlay around a bit. Whatever you put after `/hello/` will appear on the page as your messenger.","excerpt":"","slug":"adding-pages","type":"basic","title":"Adding Pages"}
Our task for this guide is to add two new pages to our Phoenix application. One will be a purely static page, and the other will take part of the path from the URL as input and pass it through to a template for display. Along the way, we will gain familiarity with the basic components of a Phoenix application: the router, controllers, views, and templates. When Phoenix generates a new application for us, it builds a top-level directory structure like this: ```text ├── _build ├── config ├── deps ├── lib ├── priv ├── test ├── web ``` Most of our work in this guide will be in the `web` directory, which looks like this when expanded: ```text ├── channels └── user_socket.ex ├── controllers │ └── page_controller.ex ├── models ├── static │ ├── assets │ | ├── images | | | └── phoenix.png | | └── favicon.ico | | └── robots.txt │ | ├── vendor ├── templates │ ├── layout │ │ └── app.html.eex │ └── page │ └── index.html.eex └── views | ├── error_helpers.ex | ├── error_view.ex | ├── layout_view.ex | └── page_view.ex ├── router.ex ├── gettext.ex ├── web.ex ``` All of the files which are currently in the `controllers`, `templates`, and `views` directories are there to create the "Welcome to Phoenix!" page we saw in the last guide. We will see how we can re-use some of that code shortly. By convention, in the development environment, anything in the `web` directory will be automatically recompiled when there is a new web request. All of our application's static assets live in `priv/static` in the directory appropriate for each type of file - css, images or js. We place assets that require a build phase into `web/static`, and the source files are built into their respective `app.js` / `app.css` bundles within `priv/static`. We won't be making any changes here for now, but it is good to know where to look for future reference. ```text priv └── static └── images └── phoenix.png ``` ```text web └── static ├── assets | ├── css | | └── app.css | ├── js | │ └── app.js | └── vendor ``` The `lib` directory also contains files we should know about. Our application's endpoint is at `lib/hello_phoenix/endpoint.ex`, and our application file (which starts our application and its supervision tree) is at `lib/hello_phoenix.ex`. ```text lib ├── hello_phoenix | ├── endpoint.ex │ └── repo.ex └── hello_phoenix.ex ``` Unlike the `web` directory, Phoenix won't recompile files inside of `lib` when there is a new web request. This is intentional! The distinction between `web` and `lib` provides a convention for the different ways that we handle state inside of our application. The `web` directory contains anything whose state lasts for the duration of a web request. The `lib` directory contains both shared modules and anything that needs to manage state outside of the duration of a web request. Enough prep, let's get on with our first new Phoenix page! ### A New Route Routes map unique HTTP verb/path pairs to controller/action pairs which will handle them. Phoenix generates a router file for us in new applications at `web/router.ex`. This is where we will be working for this section. The route for our "Welcome to Phoenix!" page from the previous Up And Running Guide looks like this. ```elixir get "/", PageController, :index ``` Let's digest what this route is telling us. Visiting [http://localhost:4000/](http://localhost:4000/) issues an HTTP `GET` request to the root path. All requests like this will be handled by the `index` function in the `HelloPhoenix.PageController` module defined in `web/controllers/page_controller.ex`. The page we are going to build will simply say "Hello World, from Phoenix!" when we point our browser to [http://localhost:4000/hello](http://localhost:4000/hello). The first thing we need to do to create that page is define a route for it. Let's open up `web/router.ex` in a text editor. It should currently look like this: ```elixir defmodule HelloPhoenix.Router do use HelloPhoenix.Web, :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 "/", HelloPhoenix do pipe_through :browser # Use the default browser stack get "/", PageController, :index end # Other scopes may use custom stacks. # scope "/api", HelloPhoenix do # pipe_through :api # end end ``` For now, we'll ignore the pipelines and the use of `scope` here and just focus on adding a route. (We cover these topics in the [Routing Guide](http://www.phoenixframework.org/docs/routing), if you're curious.) Let's add a new route to the router that maps a `GET` request for `/hello` to the `index` action of a soon-to-be-created `HelloPhoenix.HelloController`: ```elixir get "/hello", HelloController, :index ``` The `scope "/"` block of our `router.ex` file should now look like this: ```elixir scope "/", HelloPhoenix do pipe_through :browser # Use the default browser stack get "/", PageController, :index get "/hello", HelloController, :index end ``` ### A New Controller Controllers are Elixir modules, and actions are Elixir functions defined in them. The purpose of actions is to gather any data and perform any tasks needed for rendering. Our route specifies that we need a `HelloPhoenix.HelloController` module with an `index/2` action. To make that happen, let's create a new `web/controllers/hello_controller.ex` file, and make it look like the following: ```elixir defmodule HelloPhoenix.HelloController do use HelloPhoenix.Web, :controller def index(conn, _params) do render conn, "index.html" end end ``` We'll save a discussion of `use HelloPhoenix.Web, :controller` for the [Controllers Guide](http://www.phoenixframework.org/docs/controllers). For now, let's focus on the `index/2` action. All controller actions take two arguments. The first is `conn`, a struct which holds a ton of data about the request. The second is `params`, which are the request parameters. Here, we are not using `params`, and we avoid compiler warnings by adding the leading `_`. The core of this action is `render conn, "index.html"`. This tells Phoenix to find a template called `index.html.eex` and render it. Phoenix will look for the template in a directory named after our controller, so `web/templates/hello`. > Note: Using an atom as the template name will also work here, `render conn, :index`, but the template will be chosen based off the Accept headers, e.g. `"index.html"` or `"index.json"`. The modules responsible for rendering are views, and we'll make a new one of those next. ### A New View Phoenix views have several important jobs. They render templates. They also act as a presentation layer for raw data from the controller, preparing it for use in a template. Functions which perform this transformation should go in a view. As an example, say we have a data structure which represents a user with a `first_name` field and a `last_name` field, and in a template, we want to show the user's full name. We could write code in the template to merge those fields into a full name, but the better approach is to write a function in the view to do it for us, then call that function in the template. The result is a cleaner and more legible template. In order to render any templates for our `HelloController`, we need a `HelloView`. The names are significant here - the first part of the names of the view and controller must match. Let's create an empty one for now, and leave a more detailed description of views for later. Create `web/views/hello_view.ex` and make it look like this: ```elixir defmodule HelloPhoenix.HelloView do use HelloPhoenix.Web, :view end ``` ### A New Template Phoenix templates are just that, templates into which data can be rendered. The standard templating engine Phoenix uses is EEx, which stands for [Embedded Elixir](http://elixir-lang.org/docs/stable/eex/). All of our template files will have the `.eex` file extension. Templates are scoped to a view, which are scoped to controller. Phoenix creates a `web/templates` directory where we can put all these. It is best to namespace these for organization, so for our hello page, that means we need to create a `hello` directory under `web/templates` and then create an `index.html.eex` file within it. Let's do that now. Create `web/templates/hello/index.html.eex` and make it look like this: ```html <div class="jumbotron"> <h2>Hello World, from Phoenix!</h2> </div> ``` Now that we've got the route, controller, view, and template, we should be able to point our browsers at [http://localhost:4000/hello](http://localhost:4000/hello) and see our greeting from Phoenix! (In case you stopped the server along the way, the task to restart it is `mix phoenix.server`.) ![Phoenix Greets Us](/images/hello-from-phoenix.png) There are a couple of interesting things to notice about what we just did. We didn't need to stop and re-start the server while we made these changes. Yes, Phoenix has hot code reloading! Also, even though our `index.html.eex` file consisted of only a single `div` tag, the page we get is a full HTML document. Our index template is rendered into the application layout - `web/templates/layout/app.html.eex`. If you open it, you'll see a line that looks like this: <%= render @view_module, @view_template, assigns %> which is what renders our template into the layout before the HTML is sent off to the browser. ## Another New Page Let's add just a little complexity to our application. We're going to add a new page that will recognize a piece of the URL, label it as a "messenger" and pass it through the controller into the template so our messenger can say hello. As we did last time, the first thing we'll do is create a new route. ### A New Route For this exercise, we're going to re-use the `HelloController` we just created and just add a new `show` action. We'll add a line just below our last route, like this: ```elixir scope "/", HelloPhoenix do pipe_through :browser # Use the default browser stack. get "/", PageController, :index get "/hello", HelloController, :index get "/hello/:messenger", HelloController, :show end ``` Notice that we put the atom `:messenger` in the path. Phoenix will take whatever value that appears in that position in the URL and pass a [Map](http://elixir-lang.org/docs/stable/elixir/Map.html) with the key `messenger` pointing to that value to the controller. For example, if we point the browser at: [http://localhost:4000/hello/Frank](http://localhost:4000/hello/Frank), the value of ":messenger" will be "Frank". ### A New Action Requests to our new route will be handled by the `HelloPhoenix.HelloController` `show` action. We already have the controller at `web/controllers/hello_controller.ex`, so all we need to do is edit that file and add a `show` action to it. This time, we'll need to keep one of the items in the map of params that gets passed into the action, so that we can pass it (the messenger) to the template. To do that, we add this show function to the controller: ```elixir def show(conn, %{"messenger" => messenger}) do render conn, "show.html", messenger: messenger end ``` There are a couple of things to notice here. We pattern match against the params passed into the show function so that the `messenger` variable will be bound to the value we put in the `:messenger` position in the URL. For example, if our URL is [http://localhost:4000/hello/Frank](http://localhost:4000/hello/Frank), the messenger variable would be bound to `Frank`. Within the body of the `show` action, we also pass a third argument into the render function, a key/value pair where `:messenger` is the key, and the `messenger` variable is passed as the value. > Note: If the body of the action needs access to the full map of parameters bound to the params variable in addition to the bound messenger variable, we could define `show/2` like this: ```elixir def show(conn, %{"messenger" => messenger} = params) do ... end ``` It's good to remember that the keys to the `params` map will always be strings, and that the equals sign does not represent assignment, but is instead a [pattern match](http://elixir-lang.org/getting-started/pattern-matching.html) assertion. ### A New Template For the last piece of this puzzle, we'll need a new template. Since it is for the `show` action of the `HelloController`, it will go into the `web/templates/hello` directory and be called `show.html.eex`. It will look surprisingly like our `index.html.eex` template, except that we will need to display the name of our messenger. To do that, we'll use the special EEx tags for executing Elixir expressions - `<%= %>`. Notice that the initial tag has an equals sign like this: `<%=` . That means that any Elixir code that goes between those tags will be executed, and the resulting value will replace the tag. If the equals sign were missing, the code would still be executed, but the value would not appear on the page. And this is what the template should look like: ```html <div class="jumbotron"> <h2>Hello World, from <%= @messenger %>!</h2> </div> ``` Our messenger appears as `@messenger`. In this case, this is not a module attribute. It is special bit of metaprogrammed syntax which stands in for `Map.get(assigns, :messenger)`. The result is much nicer on the eyes and much easier to work with in a template. We're done. If you point your browser here: [http://localhost:4000/hello/Frank](http://localhost:4000/hello/Frank), you should see a page that looks like this: [block:image] { "images": [ { "image": [ "https://files.readme.io/tXWKhaWATbuiAnIZLplM_hello-from-phoenix.png", "hello-from-phoenix.png", "1602", "886", "#603129", "" ], "caption": "Hello World, from Phoenix!" } ] } [/block] Play around a bit. Whatever you put after `/hello/` will appear on the page as your messenger.