From 64ab5740a4c69337590a3c859ed52ac0744741a4 Mon Sep 17 00:00:00 2001 From: Kian-Meng Ang Date: Sun, 25 Sep 2022 00:56:57 +0800 Subject: [PATCH] Fix markdown issues (#4972) --- CONTRIBUTING.md | 12 +++++++----- README.md | 31 +++++++++++++++--------------- guides/asset_management.md | 12 ++++++++---- guides/contexts.md | 15 ++++++--------- guides/controllers.md | 2 -- guides/deployment/fly.md | 9 ++++----- guides/deployment/heroku.md | 12 +++++++----- guides/directory_structure.md | 1 - guides/ecto.md | 2 +- guides/howto/custom_error_pages.md | 1 + guides/introduction/community.md | 5 +++-- guides/mix_tasks.md | 3 +++ guides/plug.md | 5 +++-- guides/real_time/channels.md | 9 +++++---- guides/request_lifecycle.md | 10 +++++----- guides/routing.md | 3 ++- guides/telemetry.md | 3 +-- guides/testing/testing.md | 11 ++++++----- guides/views.md | 1 - 19 files changed, 78 insertions(+), 69 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5850788945..5d4f32d969 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ making it easier for developers to [contribute to Phoenix](#pull-requests). ## Bug reports A bug is either a _demonstrable problem_ that is caused by the code in the repository, -or indicate missing, unclear, or misleading documentation. Good bug reports are extremely +or indicate missing, unclear, or misleading documentation. Good bug reports are extremely helpful - thank you! Guidelines for bug reports: @@ -134,8 +134,10 @@ in order to craft an excellent pull request: ```bash # Clone your fork of the repo into the current directory git clone https://github.com//phoenix + # Navigate to the newly cloned directory cd phoenix + # Assign the original repo to a remote called "upstream" git remote add upstream https://github.com/phoenixframework/phoenix ``` @@ -216,10 +218,10 @@ complete, the better. For formatting the guides: -- We use the "elixir" code fence for all module code. -- We use the "iex" for IEx sessions. -- We use the "console" code fence for shell commands. -- We use the "html" code fence for html templates, even if there is elixir code +- We use the `elixir` code fence for all module code. +- We use the `iex` for IEx sessions. +- We use the `console` code fence for shell commands. +- We use the `html` code fence for html templates, even if there is elixir code in the template. - We use backticks for filenames and directory paths. - We use backticks for module names, function names, and variable names. diff --git a/README.md b/README.md index bff6a5a5fe..1f21739a42 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,20 @@ ![phoenix logo](https://raw.githubusercontent.com/phoenixframework/phoenix/master/priv/static/phoenix.png) + > Peace of mind from prototype to production. [![Build Status](https://github.com/phoenixframework/phoenix/workflows/CI/badge.svg)](https://github.com/phoenixframework/phoenix/actions/workflows/ci.yml) [![Hex.pm](https://img.shields.io/hexpm/v/phoenix.svg)](https://hex.pm/packages/phoenix) [![Documentation](https://img.shields.io/badge/documentation-gray)](https://hexdocs.pm/phoenix) ## Getting started -See the official site at https://www.phoenixframework.org/ +See the official site at . -Install the latest version of Phoenix by following the instructions at https://hexdocs.pm/phoenix/installation.html#phoenix +Install the latest version of Phoenix by following the instructions at . ## Documentation -API documentation is available at [https://hexdocs.pm/phoenix](https://hexdocs.pm/phoenix) +API documentation is available at . -Phoenix.js documentation is available at [https://hexdocs.pm/phoenix/js](https://hexdocs.pm/phoenix/js) +Phoenix.js documentation is available at . ## Contributing @@ -28,8 +29,8 @@ You can create a new project using the latest Phoenix source installer (the `phx 3. Run the `phx.new` Mix task from within the `installer` directory, for example: ```bash -$ cd phoenix/installer -$ mix phx.new dev_app --dev +cd phoenix/installer +mix phx.new dev_app --dev ``` The `--dev` flag will configure your new project's `:phoenix` dep as a relative path dependency, pointing to your local Phoenix checkout: @@ -44,30 +45,30 @@ To create projects outside of the `installer/` directory, add the latest archive To build the documentation from source: ```bash -$ npm install --prefix assets -$ MIX_ENV=docs mix docs +npm install --prefix assets +MIX_ENV=docs mix docs ``` To build Phoenix from source: ```bash -$ mix deps.get -$ mix compile +mix deps.get +mix compile ``` To build the Phoenix installer from source: ```bash -$ mix deps.get -$ mix compile -$ mix archive.build +mix deps.get +mix compile +mix archive.build ``` ### Building phoenix.js ```bash -$ cd assets -$ npm install +cd assets +npm install ``` ## Important links diff --git a/guides/asset_management.md b/guides/asset_management.md index 953c1ac8bc..da03aeae23 100644 --- a/guides/asset_management.md +++ b/guides/asset_management.md @@ -14,13 +14,17 @@ Finally, all other assets, that usually don't have to be preprocessed, go direct If you want to import JavaScript dependencies, you have two options to add them to your application: - 1. Vendor those dependencies inside your project and import them in your "assets/js/app.js" using a relative path: +1. Vendor those dependencies inside your project and import them in your "assets/js/app.js" using a relative path: - import topbar from "../vendor/topbar" + ```js + import topbar from "../vendor/topbar" + ``` - 2. Call `npm install topbar --save` inside your assets directory and `esbuild` will be able to automatically pick them up: +2. Call `npm install topbar --save` inside your assets directory and `esbuild` will be able to automatically pick them up: - import topbar from "topbar" + ```js + import topbar from "topbar" + ``` ## CSS diff --git a/guides/contexts.md b/guides/contexts.md index 5782021e04..24477adacd 100644 --- a/guides/contexts.md +++ b/guides/contexts.md @@ -105,13 +105,13 @@ $ mix ecto.migrate Before we jump into the generated code, let's start the server with `mix phx.server` and visit [http://localhost:4000/products](http://localhost:4000/products). Let's follow the "New Product" link and click the "Save" button without providing any input. We should be greeted with the following output: -``` +```text Oops, something went wrong! Please check the errors below. ``` When we submit the form, we can see all the validation errors inline with the inputs. Nice! Out of the box, the context generator included the schema fields in our form template and we can see our default validations for required inputs are in effect. Let's enter some example product data and resubmit the form: -``` +```text Product created successfully. Title: Metaprogramming Elixir @@ -312,7 +312,7 @@ We modified our `show` action to pipe our fetched product into `Catalog.inc_page We can also see our atomic update in action in the ecto debug logs: -``` +```text [debug] QUERY OK source="products" db=0.5ms idle=834.5ms UPDATE "products" AS p0 SET "views" = p0."views" + $1 WHERE (p0."id" = $2) RETURNING p0."views" [1, 1] ``` @@ -427,7 +427,6 @@ INSERT INTO "categories" ("title","inserted_at","updated_at") VALUES ($1,$2,$3) Perfect. Before we integrate categories in the web layer, we need to let our context know how to associate products and categories. First, open up `lib/hello/catalog/product.ex` and add the following association: - ```diff + alias Hello.Catalog.Category @@ -448,7 +447,6 @@ We used `Ecto.Schema`'s `many_to_many` macro to let Ecto know how to associate o With our schema associations set up, we can implement the selection of categories in our product form. To do so, we need to translate the user input of catalog IDs from the front-end to our many-to-many association. Fortunately Ecto makes this a breeze now that our schema is set up. Open up your catalog context and make the following changes: - ```diff + alias Hello.Catalog.Category @@ -543,7 +541,7 @@ We added a `category_select` above our save button. Now let's try it out. Next, Now if we start the server with `mix phx.server` and visit [http://localhost:4000/products/new](http://localhost:4000/products/new), we'll see the new category multiple select input. Enter some valid product details, select a category or two, and click save. -``` +```text Title: Elixir Flashcards Description: Flash card set for the Elixir programming language Price: 5.000000 @@ -882,7 +880,7 @@ The `link` function component from `Phoenix.LiveView.Helpers` accepts a `:method Let's try it out. Start your server with `mix phx.server` and visit a product page. If we try clicking the add to cart link, we'll be greeted by an error page with the following logs in the console: -``` +```text [info] POST /cart_items [debug] Processing with HelloWeb.CartItemController.create/2 Parameters: %{"_method" => "post", "product_id" => "1", ...} @@ -987,7 +985,7 @@ Now that we can calculate price totals, let's try it out! Visit [`http://localho Our cart page is almost complete, but submitting the form will yield yet another error. -``` +```text Request: POST /cart ** (exit) an exception was raised: ** (UndefinedFunctionError) function HelloWeb.CartController.update/2 is undefined or private @@ -1197,7 +1195,6 @@ $ mix ecto.migrate Before we render information about our orders, we need to ensure our order data is fully populated and can be looked up by a current user. Open up your orders context in `lib/hello/orders.ex` and replace your `get_order!/1` function by a new `get_order!/2` definition: - ```elixir def get_order!(user_uuid, id) do Order diff --git a/guides/controllers.md b/guides/controllers.md index 06969bc75b..a30accf3a2 100644 --- a/guides/controllers.md +++ b/guides/controllers.md @@ -274,7 +274,6 @@ Reloading [http://localhost:4000](http://localhost:4000) should show us a comple To be specific about the content type, we can use [`put_resp_content_type/2`] in conjunction with [`send_resp/3`]. - ```elixir def index(conn, _params) do conn @@ -499,7 +498,6 @@ end Whenever the `with` conditions do not match, `HelloWeb.MyFallbackController` will receive the original `conn` as well as the result of the action and respond accordingly. - [`/hello/Frank`]: http://localhost:4000/hello/Frank [`assign/3`]: `Plug.Conn.assign/3` [`clear_flash/1`]: `Phoenix.Controller.clear_flash/1` diff --git a/guides/deployment/fly.md b/guides/deployment/fly.md index fe1174bdee..cb14aada51 100644 --- a/guides/deployment/fly.md +++ b/guides/deployment/fly.md @@ -6,7 +6,7 @@ The only thing we'll need for this guide is a working Phoenix application. For t You can just: -``` +```console $ mix phx.new my_app ``` @@ -208,18 +208,17 @@ Our next step is to add the `topologies` configuration to `config/runtime.exs`. This configures `libcluster` to use the `DNSPoll` strategy and look for other deployed apps using the `$FLY_APP_NAME` on the `.internal` private network. - #### Controlling the name for our node We need to control the naming of our Elixir nodes. To help them connect up, we'll name them using this pattern: `your-fly-app-name@the.ipv6.address.on.fly`. To do this, we'll generate the release config. -``` +```console $ mix release.init ``` Then edit the generated `rel/env.sh.eex` file and add the following lines: -``` +```console ip=$(grep fly-local-6pn /etc/hosts | cut -f 1) export RELEASE_DISTRIBUTION=name export RELEASE_NODE=$FLY_APP_NAME@$ip @@ -227,7 +226,7 @@ export RELEASE_NODE=$FLY_APP_NAME@$ip After making the change, deploy your app! -``` +```console $ fly deploy ``` diff --git a/guides/deployment/heroku.md b/guides/deployment/heroku.md index 751d48b140..9902513860 100644 --- a/guides/deployment/heroku.md +++ b/guides/deployment/heroku.md @@ -95,7 +95,7 @@ https://mysterious-meadow-6277.herokuapp.com/ | https://git.heroku.com/mysteriou The buildpack uses a predefined Elixir and Erlang version, but to avoid surprises when deploying, it is best to explicitly list the Elixir and Erlang version we want in production to be the same we are using during development or in your continuous integration servers. This is done by creating a config file named `elixir_buildpack.config` in the root directory of your project with your target version of Elixir and Erlang: -``` +```console # Elixir version elixir_version=1.14.0 @@ -110,7 +110,7 @@ hook_post_compile="eval mix assets.deploy && rm -f _build/esbuild*" Finally, let's tell the build pack how to start our webserver. Create a file named `Procfile` at the root of your project: -``` +```console web: mix phx.server ``` @@ -139,7 +139,7 @@ When using this buildpack, you want to delegate all asset bundling to `npm`. So The Phoenix Static buildpack uses a predefined Node.js version, but to avoid surprises when deploying, it is best to explicitly list the Node.js version we want in production to be the same we are using during development or in your continuous integration servers. This is done by creating a config file named `phoenix_static_buildpack.config` in the root directory of your project with your target version of Node.js: -``` +```text # Node.js version node_version=10.20.1 ``` @@ -374,9 +374,11 @@ $ heroku run "POOL_SIZE=2 mix ecto.migrate" Heroku gives you the ability to connect to your dyno with an IEx shell which allows running Elixir code such as database queries. - Modify the `web` process in your Procfile to run a named node: - ``` + + ```text web: elixir --sname server -S mix phx.server ``` + - Redeploy to Heroku - Connect to the dyno with `heroku ps:exec` (if you have several applications on the same repository you will need to specify the app name or the remote name with `--app APP_NAME` or `--remote REMOTE_NAME`) - Launch an iex session with `iex --sname console --remsh server` @@ -409,7 +411,7 @@ To https://git.heroku.com/mysterious-meadow-6277.git This has to do with stale dependencies which are not getting recompiled properly. It's possible to force Heroku to recompile all dependencies on each deploy, which should fix this problem. The way to do it is to add a new file called `elixir_buildpack.config` at the root of the application. The file should contain this line: -``` +```text always_rebuild=true ``` diff --git a/guides/directory_structure.md b/guides/directory_structure.md index d30f1242d7..b1dde82ccf 100644 --- a/guides/directory_structure.md +++ b/guides/directory_structure.md @@ -68,7 +68,6 @@ You can learn more about applications in [Elixir's official docs for Application The `lib/hello/mailer.ex` file holds the `Hello.Mailer` module, which defines the main interface to deliver e-mails: - ```elixir defmodule Hello.Mailer do use Swoosh.Mailer, otp_app: :hello diff --git a/guides/ecto.md b/guides/ecto.md index 1c96cebd9f..c2846bccc4 100644 --- a/guides/ecto.md +++ b/guides/ecto.md @@ -307,7 +307,7 @@ iex> changeset = User.changeset(%User{}, params) errors: [], data: #Hello.User<>, valid?: true -> +> ``` Our new changeset is valid. diff --git a/guides/howto/custom_error_pages.md b/guides/howto/custom_error_pages.md index 0448942eeb..6a583e0b3b 100644 --- a/guides/howto/custom_error_pages.md +++ b/guides/howto/custom_error_pages.md @@ -149,6 +149,7 @@ However, implementing the `Plug.Exception` protocol by hand can be convenient in Exception actions are functions that can be triggered by the error page, and they're basically a list of maps defining a `label` and a `handler` to be executed. They are rendered in the error page as a collection of buttons and follow the format of: + ```elixir [ %{ diff --git a/guides/introduction/community.md b/guides/introduction/community.md index fb5ef58cfa..10fef641f5 100644 --- a/guides/introduction/community.md +++ b/guides/introduction/community.md @@ -7,7 +7,7 @@ There are a number of places to connect with community members at all experience * We're on Libera IRC in the [\#elixir](https://web.libera.chat/?channels=#elixir) channel. * [Request an invitation](https://elixir-slackin.herokuapp.com/) and join the #phoenix channel on [Slack](https://elixir-lang.slack.com). - + * Feel free to join and check out the #phoenix channel on [Discord](https://discord.gg/elixir). * Read about [bug reports](https://github.com/phoenixframework/phoenix/blob/master/CONTRIBUTING.md#bug-reports) or open an issue in the Phoenix [issue tracker](https://github.com/phoenixframework/phoenix/issues). @@ -21,6 +21,7 @@ There are a number of places to connect with community members at all experience * The source for these guides is [on GitHub](https://github.com/phoenixframework/phoenix/tree/master/guides). To help improve the guides, please report an [issue](https://github.com/phoenixframework/phoenix/issues) or open a [pull request](https://github.com/phoenixframework/phoenix/pulls). ## Books + * [Programming Phoenix LiveView - Interactive Elixir Web Programming Without Writing Any JavaScript - 2021 (by Bruce Tate and Sophie DeBenedetto)](https://pragprog.com/titles/liveview/programming-phoenix-liveview/) * [Real-Time Phoenix - Build Highly Scalable Systems with Channels (by Stephen Bussey - 2020)](https://pragprog.com/book/sbsockets/real-time-phoenix) @@ -38,7 +39,7 @@ There are a number of places to connect with community members at all experience * [Phoenix LiveView Free Course (by The Pragmatic Studio - 2020)](https://pragmaticstudio.com/courses/phoenix-liveview) * [Groxio LiveView: Self Study Program (by Bruce Tate - 2020)](https://grox.io/language/liveview/course) - + * [Alchemist Camp: Learn Elixir and Phoenix by building (2018-2022)](https://alchemist.camp/episodes) * [The Complete Elixir and Phoenix Bootcamp Master Functional Programming Techniques with Elixir and Phoenix while Learning to Build Compelling Web Applications (by Stephen Grider - 2017)](https://www.udemy.com/the-complete-elixir-and-phoenix-bootcamp-and-tutorial/) diff --git a/guides/mix_tasks.md b/guides/mix_tasks.md index 8f60202471..fce0afae94 100644 --- a/guides/mix_tasks.md +++ b/guides/mix_tasks.md @@ -362,6 +362,7 @@ If we don't specify a router for this task, it will default to the router Phoeni $ mix phx.routes GET / TaskTester.PageController.index/2 ``` + We can also specify an individual router if we have more than one for our application. ```console @@ -377,12 +378,14 @@ This is the task we use to get our application running. It takes no arguments at $ mix phx.server [info] Running TaskTesterWeb.Endpoint with Cowboy on port 4000 (http) ``` + It will silently ignore our `DoesNotExist` argument: ```console $ mix phx.server DoesNotExist [info] Running TaskTesterWeb.Endpoint with Cowboy on port 4000 (http) ``` + 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 phx.server`. ```console diff --git a/guides/plug.md b/guides/plug.md index 0278bfe408..0578969e27 100644 --- a/guides/plug.md +++ b/guides/plug.md @@ -13,6 +13,7 @@ At the simplest level, the Plug specification comes in two flavors: *function pl ## Function plugs In order to act as a plug, a function needs to: + 1. accept a connection struct (`%Plug.Conn{}`) as its first argument, and connection options as its second one; 2. return a connection struct. @@ -146,7 +147,7 @@ The default endpoint plugs do quite a lot of work. Here they are in order: - `Plug.Static` - serves static assets. Since this plug comes before the logger, requests for static assets are not logged. -- `Phoenix.LiveDashboard.RequestLogger` - sets up the _Request Logger_ for Phoenix LiveDashboard, this will allow you to have the option to either pass a query parameter to stream requests logs or to enable/disable a cookie that streams requests logs from your dashboard. +- `Phoenix.LiveDashboard.RequestLogger` - sets up the *Request Logger* for Phoenix LiveDashboard, this will allow you to have the option to either pass a query parameter to stream requests logs or to enable/disable a cookie that streams requests logs from your dashboard. - `Plug.RequestId` - generates a unique request ID for each request. @@ -172,6 +173,7 @@ In the middle of the endpoint, there is also a conditional block: ``` This block is only executed in development. It enables: + * live reloading - if you change a CSS file, they are updated in-browser without refreshing the page; * [code reloading](`Phoenix.CodeReloader`) - so we can see changes to our application without restarting the server; * check repo status - which makes sure our database is up to date, raising a readable and actionable error otherwise. @@ -303,7 +305,6 @@ At the end of the day, by replacing the nested blocks of code with a flattened s To learn more about plugs, see the documentation for the [Plug project](`Plug`), which provides many built-in plugs and functionalities. - [`init/1`]: `c:Plug.init/1` [`call/2`]: `c:Plug.call/2` [`assign/3`]: `Plug.Conn.assign/3` diff --git a/guides/real_time/channels.md b/guides/real_time/channels.md index 714ec142fb..6a1494ddbb 100644 --- a/guides/real_time/channels.md +++ b/guides/real_time/channels.md @@ -145,6 +145,7 @@ Topics are string identifiers - names that the various layers use in order to ma ### Messages The `Phoenix.Socket.Message` module defines a struct with the following keys which denotes a valid message. From the [Phoenix.Socket.Message docs](https://hexdocs.pm/phoenix/Phoenix.Socket.Message.html). + - `topic` - The string topic or `"topic:subtopic"` pair namespace, such as `"messages"` or `"messages:123"` - `event` - The string event name, for example `"phx_join"` - `payload` - The message payload @@ -383,7 +384,7 @@ That's all there is to our basic chat app. Fire up multiple browser tabs and you When we connect, we'll often need to authenticate the client. Fortunately, this is a 4-step process with [Phoenix.Token](https://hexdocs.pm/phoenix/Phoenix.Token.html). -**Step 1 - Assign a Token in the Connection** +### Step 1 - Assign a Token in the Connection Let's say we have an authentication plug in our app called `OurAuth`. When `OurAuth` authenticates a user, it sets a value for the `:current_user` key in `conn.assigns`. Since the `current_user` exists, we can simply assign the user's token in the connection for use in the layout. We can wrap that behavior up in a private function plug, `put_user_token/2`. This could also be put in its own module as well. To make this all work, we just add `OurAuth` and `put_user_token/2` to the browser pipeline. @@ -406,7 +407,7 @@ end Now our `conn.assigns` contains the `current_user` and `user_token`. -**Step 2 - Pass the Token to the JavaScript** +### Step 2 - Pass the Token to the JavaScript Next, we need to pass this token to JavaScript. We can do so inside a script tag in `web/templates/layout/app.html.heex` right above the app.js script, as follows: @@ -415,7 +416,7 @@ Next, we need to pass this token to JavaScript. We can do so inside a script tag ``` -**Step 3 - Pass the Token to the Socket Constructor and Verify** +### Step 3 - Pass the Token to the Socket Constructor and Verify We also need to pass the `:params` to the socket constructor and verify the user token in the `connect/3` function. To do so, edit `web/channels/user_socket.ex`, as follows: @@ -439,7 +440,7 @@ let socket = new Socket("/socket", {params: {token: window.userToken}}) We used `Phoenix.Token.verify/4` to verify the user token provided by the client. `Phoenix.Token.verify/4` returns either `{:ok, user_id}` or `{:error, reason}`. We can pattern match on that return in a `case` statement. With a verified token, we set the user's id as the value to `:current_user` in the socket. Otherwise, we return `:error`. -**Step 4 - Connect to the socket in JavaScript** +### Step 4 - Connect to the socket in JavaScript With authentication set up, we can connect to sockets and channels from JavaScript. diff --git a/guides/request_lifecycle.md b/guides/request_lifecycle.md index 55c2dbeb20..8aacd7f5c1 100644 --- a/guides/request_lifecycle.md +++ b/guides/request_lifecycle.md @@ -10,11 +10,11 @@ Let's get on with our first new Phoenix page! When your browser accesses [http://localhost:4000/](http://localhost:4000/), it sends a HTTP request to whatever service is running on that address, in this case our Phoenix application. The HTTP request is made of a verb and a path. For example, the following browser requests translate into: -| Browser address bar | Verb | Path | -|:-----------------------------------|:-----|:--------------| -| http://localhost:4000/ | GET | / | -| http://localhost:4000/hello | GET | /hello | -| http://localhost:4000/hello/world | GET | /hello/world | +| Browser address bar | Verb | Path | +|:------------------------------------|:-----|:--------------| +| | GET | / | +| | GET | /hello | +| | GET | /hello/world | There are other HTTP verbs. For example, submitting a form typically uses the POST verb. diff --git a/guides/routing.md b/guides/routing.md index 90dc7ffe8e..05d892c0b5 100644 --- a/guides/routing.md +++ b/guides/routing.md @@ -119,7 +119,7 @@ resources "/posts", PostController, only: [:index, :show] Running `mix phx.routes` shows that we now only have the routes to the index and show actions defined. -``` +```console GET /posts HelloWeb.PostController :index GET /posts/:id HelloWeb.PostController :show ``` @@ -213,6 +213,7 @@ resources "/users", UserController do resources "/posts", PostController end ``` + When we run `mix phx.routes` now, in addition to the routes we saw for `users` above, we get the following set of routes: ```elixir diff --git a/guides/telemetry.md b/guides/telemetry.md index 585d8c244c..f8f1c47319 100644 --- a/guides/telemetry.md +++ b/guides/telemetry.md @@ -449,7 +449,6 @@ Hopefully, this gives you some inspiration on how to use the `:tag_values` option. Just remember to keep this function fast since it is called on every event. - ## Periodic measurements You might want to periodically measure key-value pairs within @@ -530,7 +529,7 @@ their own (in alphabetical order, please): If you need custom metrics and instrumentation in your application, you can utilize the `:telemetry` package -(https://hexdocs.pm/telemetry) just like your favorite +() just like your favorite frameworks and libraries. Here is an example of a simple GenServer that emits telemetry diff --git a/guides/testing/testing.md b/guides/testing/testing.md index f10464a3f3..59405afcc0 100644 --- a/guides/testing/testing.md +++ b/guides/testing/testing.md @@ -116,7 +116,6 @@ end There is a lot to unpack here. - The second line says this is a case template. This is a ExUnit feature that allows developers to replace the built-in `use ExUnit.Case` by their own case. This line is pretty much what allows us to write `use HelloWeb.ConnCase` at the top of our controller tests. Now that we have made this module a case template, we can define callbacks that are invoked on certain occasions. The `using` callback defines code to be injected on every module that calls `use HelloWeb.ConnCase`. In this case, it starts by setting the `@endpoint` module attribute with the name of our endpoint. @@ -493,10 +492,12 @@ database: "hello_test#{System.get_env("MIX_TEST_PARTITION")}", By default, the `MIX_TEST_PARTITION` environment variable has no value, and therefore it has no effect. But in your CI server, you can, for example, split your test suite across machines by using four distinct commands: - $ MIX_TEST_PARTITION=1 mix test --partitions 4 - $ MIX_TEST_PARTITION=2 mix test --partitions 4 - $ MIX_TEST_PARTITION=3 mix test --partitions 4 - $ MIX_TEST_PARTITION=4 mix test --partitions 4 +```console +$ MIX_TEST_PARTITION=1 mix test --partitions 4 +$ MIX_TEST_PARTITION=2 mix test --partitions 4 +$ MIX_TEST_PARTITION=3 mix test --partitions 4 +$ MIX_TEST_PARTITION=4 mix test --partitions 4 +``` That's all you need to do and ExUnit and Phoenix will take care of all rest, including setting up the database for each distinct partition with a distinct name. diff --git a/guides/views.md b/guides/views.md index 49aebdae66..316fbf13e5 100644 --- a/guides/views.md +++ b/guides/views.md @@ -388,7 +388,6 @@ end Phoenix has a view called `ErrorView` which lives in `lib/hello_web/views/error_view.ex`. The purpose of `ErrorView` is to handle errors in a general way, from one centralized location. Similar to the views we built in this guide, error views can return both HTML and JSON responses. See the [Custom Error Pages How-To](custom_error_pages.html) for more information. - [welcome page]: http://localhost:4000 [`render/3`]: `Phoenix.View.render/3` [`render_many/3`]: `Phoenix.View.render_many/3`