Repository: phoenixframework/phoenix
Pull request #6248 (2025-05-13 19:56:53)

Fixes to Cross-context Boundaries guide
Ran into some errors while going through the context guides in `1.8.0-rc.3` along with an update to a diff section that looked old.


Patch:
diff --git a/guides/data_modelling/cross_context_boundaries.md b/guides/data_modelling/cross_context_boundaries.md
index 28268caa4..437beb8a7 100644
--- a/guides/data_modelling/cross_context_boundaries.md
+++ b/guides/data_modelling/cross_context_boundaries.md
@@ -232,7 +232,7 @@ Because we used `mix phx.gen.auth`, we already have a real authentication system
 +   if cart = ShoppingCart.get_cart(scope) do
 +     assign(conn, :cart, cart)
 +   else
-+     {:ok, new_cart} = ShoppingCart.create_cart(scope)
++     {:ok, new_cart} = ShoppingCart.create_cart(scope, %{})
 +     assign(conn, :cart, new_cart)
 +   end
 + end
@@ -347,7 +347,7 @@ Let's implement the new interface for the `ShoppingCart` context API in `lib/hel
             |> Repo.insert() do
        broadcast(scope, {:created, cart})
 -      {:ok, cart}
-+      {:ok, get_cart(scope, cart.id)}
++      {:ok, get_cart(scope)}
      end
    end
 +
@@ -390,8 +390,8 @@ With our new cart functions in place, we can now expose the "Add to cart" button
 
 ```diff
 ...
-     <.button href={~p"/products/#{@product}/edit"}>
-       Edit product
+     <.button variant="primary" navigate={~p"/products/#{@product}/edit?return_to=show"}>
+       <.icon name="hero-pencil-square" /> Edit product
      </.button>
 +    <.button href={~p"/cart_items?product_id=#{@product.id}"} method="post">
 +      Add to cart
diff --git a/guides/real_time/channels.md b/guides/real_time/channels.md
index 7436cda32..eaca2fbd1 100644
--- a/guides/real_time/channels.md
+++ b/guides/real_time/channels.md
@@ -107,7 +107,8 @@ In your Phoenix app's `Endpoint` module, a `socket` declaration specifies which
 ```elixir
 socket "/socket", HelloWeb.UserSocket,
   websocket: true,
-  longpoll: false
+  longpoll: false,
+  auth_token: true
 ```
 
 Phoenix comes with two default transports: websocket and longpoll. You can configure them directly via the `socket` declaration.
@@ -117,7 +118,7 @@ Phoenix comes with two default transports: websocket and longpoll. You can confi
 On the client side, you will establish a socket connection to the route above:
 
 ```javascript
-let socket = new Socket("/socket", {params: {token: window.userToken}})
+let socket = new Socket("/socket", {authToken: window.userToken})
 ```
 
 On the server, Phoenix will invoke `HelloWeb.UserSocket.connect/2`, passing your parameters and the initial socket state. Within the socket, you can authenticate and identify a socket connection and set default socket assigns. The socket is also where you define your channel routes.
diff --git a/guides/real_time/presence.md b/guides/real_time/presence.md
index 32271b855..df3cec431 100644
--- a/guides/real_time/presence.md
+++ b/guides/real_time/presence.md
@@ -93,7 +93,7 @@ We can see presence working by adding the following to `assets/js/app.js`:
 ```javascript
 import {Socket, Presence} from "phoenix"
 
-let socket = new Socket("/socket", {params: {token: window.userToken}})
+let socket = new Socket("/socket", {authToken: window.userToken})
 let channel = socket.channel("room:lobby", {name: window.location.search.split("=")[1]})
 let presence = new Presence(channel)
 
diff --git a/guides/request_lifecycle.md b/guides/request_lifecycle.md
index 06bef9610..950ca89c7 100644
--- a/guides/request_lifecycle.md
+++ b/guides/request_lifecycle.md
@@ -8,7 +8,7 @@ Let's get on with our first new Phoenix page!
 
 ## Adding a new 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:
+When your browser accesses [http://localhost:4000/](http://localhost:4000/), it sends an 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          |
 |:------------------------------------|:-----|:--------------|
@@ -26,7 +26,7 @@ The router maps unique HTTP verb/path pairs to controller/action pairs which wil
 
 Phoenix generates a router file for us in new applications at `lib/hello_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](up_and_running.html) looks like this.
+The route for our "Welcome to Phoenix!" page from the previous [Up And Running Guide](up_and_running.html) looks like this:
 
 ```elixir
 get "/", PageController, :home
@@ -133,11 +133,11 @@ defmodule HelloWeb.HelloHTML do
 end
 ```
 
-We defined a function that receives `assigns` as arguments and used [the `~H` sigil](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2) to specify the content we want to render. Inside the `~H` sigil, we used a templating language called HEEx, which stands for "HTML+EEx". `EEx` is a library for embedding Elixir that ships as part of Elixir itself. "HTML+EEx" is a Phoenix extension of EEx that is HTML aware, with support for HTML validation, components, and automatic escaping of values. The latter protects you from security vulnerabilities like Cross-Site-Scripting with no extra work on your part.
+We defined a function that receives `assigns` as arguments and used [the `~H` sigil](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#sigil_H/2) to specify the content we want to render. Inside the `~H` sigil, we used a templating language called HEEx, which stands for "HTML+EEx". `EEx` is a library for embedding Elixir that ships as part of Elixir itself. "HTML+EEx" is a Phoenix extension of EEx that is HTML aware, with support for HTML validation, components, and automatic escaping of values. The latter protects you from security vulnerabilities like Cross-Site Scripting with no extra work on your part.
 
 A template file works in the same way. Function components are great for smaller templates and separate files are a good choice when you have a lot of markup or your functions start to feel unmanageable.
 
-Let's give it a try by defining a template in its own file. First delete our `def index(assigns)` function from above and replace it with an `embed_templates` declaration:
+Let's give it a try by defining a template in its own file. First, delete our `def index(assigns)` function from above and replace it with an `embed_templates` declaration:
 
 ```elixir
 defmodule HelloWeb.HelloHTML do
diff --git a/priv/templates/phx.gen.socket/socket.js b/priv/templates/phx.gen.socket/socket.js
index a308171db..236d998b0 100644
--- a/priv/templates/phx.gen.socket/socket.js
+++ b/priv/templates/phx.gen.socket/socket.js
@@ -5,52 +5,11 @@
 import {Socket} from "phoenix"
 
 // And connect to the path in "<%= web_prefix %>/endpoint.ex". We pass the
-// token for authentication. Read below how it should be used.
-let socket = new Socket("/socket", {params: {token: window.userToken}})
-
-// When you connect, you'll often need to authenticate the client.
-// For example, imagine you have an authentication plug, `MyAuth`,
-// which authenticates the session and assigns a `:current_user`.
-// If the current user exists you can assign the user's token in
-// the connection for use in the layout.
-//
-// In your "<%= web_prefix %>/router.ex":
-//
-//     pipeline :browser do
-//       ...
-//       plug MyAuth
-//       plug :put_user_token
-//     end
-//
-//     defp put_user_token(conn, _) do
-//       if current_user = conn.assigns[:current_user] do
-//         token = Phoenix.Token.sign(conn, "user socket", current_user.id)
-//         assign(conn, :user_token, token)
-//       else
-//         conn
-//       end
-//     end
-//
-// Now you need to pass this token to JavaScript. You can do so
-// inside a script tag in "<%= web_prefix %>/components/layouts/root.html.heex":
-//
-//     <script>window.userToken = "<%%= assigns[:user_token] %>";</script>
-//
-// You will need to verify the user token in the "connect/3" function
-// in "<%= web_prefix %>/channels/user_socket.ex":
-//
-//     def connect(%{"token" => token}, socket, _connect_info) do
-//       # max_age: 1209600 is equivalent to two weeks in seconds
-//       case Phoenix.Token.verify(socket, "user socket", token, max_age: 1_209_600) do
-//         {:ok, user_id} ->
-//           {:ok, assign(socket, :user, user_id)}
-//
-//         {:error, reason} ->
-//           :error
-//       end
-//     end
+// token for authentication.
 //
-// Finally, connect to the socket:
+// Read the [`Using Token Authentication`](https://hexdocs.pm/phoenix/channels.html#using-token-authentication)
+// section to see how the token should be used.
+let socket = new Socket("/socket", {authToken: window.userToken})
 socket.connect()
 
 // Now that you are connected, you can join channels with a topic.


Test patch:
diff --git a/test/mix/tasks/phx.gen.socket_test.exs b/test/mix/tasks/phx.gen.socket_test.exs
index 7fa277374..db83baa14 100644
--- a/test/mix/tasks/phx.gen.socket_test.exs
+++ b/test/mix/tasks/phx.gen.socket_test.exs
@@ -33,7 +33,7 @@ defmodule Mix.Tasks.Phx.Gen.SocketTest do
         assert file =~ ~S|// you uncomment its entry in "assets/js/app.js".|
 
         assert file =~ ~S|// And connect to the path in "lib/phoenix_web/endpoint.ex".|
-        assert file =~ ~S|let socket = new Socket("/socket", {params: {token: window.userToken}})|
+        assert file =~ ~S|let socket = new Socket("/socket", {authToken: window.userToken})|
 
         assert file =~ ~S|let channel = socket.channel("room:42", {})|
         assert file =~ ~S|channel.join()|
@@ -74,7 +74,9 @@ defmodule Mix.Tasks.Phx.Gen.SocketTest do
         assert file =~ ~S|import {Socket} from "phoenix"|
 
         assert file =~ ~S|// And connect to the path in "lib/phoenix/endpoint.ex".|
-        assert file =~ ~S|In your "lib/phoenix/router.ex":|
+
+        assert file =~
+                 ~S|Read the [`Using Token Authentication`](https://hexdocs.pm/phoenix/channels.html#using-token-authentication)|
 
         assert file =~ ~S|let channel = socket.channel("room:42", {})|
         assert file =~ ~S|channel.join()|
@@ -101,9 +103,10 @@ defmodule Mix.Tasks.Phx.Gen.SocketTest do
         assert file =~ ~S|import {Socket} from "phoenix"|
 
         assert file =~ ~S|// And connect to the path in "lib/phoenix_web/endpoint.ex".|
-        assert file =~ ~S|let socket = new Socket("/socket", {params: {token: window.userToken}})|
+        assert file =~ ~S|let socket = new Socket("/socket", {authToken: window.userToken})|
 
-        assert file =~ ~S|In your "lib/phoenix_web/router.ex":|
+        assert file =~
+                 ~S|Read the [`Using Token Authentication`](https://hexdocs.pm/phoenix/channels.html#using-token-authentication)|
 
         assert file =~ ~S|let channel = socket.channel("room:42", {})|
         assert file =~ ~S|channel.join()|