diff --git a/lib/phoenix/controller/flash.ex b/lib/phoenix/controller/flash.ex index 634582ca41..d50bf6c2a7 100644 --- a/lib/phoenix/controller/flash.ex +++ b/lib/phoenix/controller/flash.ex @@ -53,7 +53,8 @@ defmodule Phoenix.Controller.Flash do """ def put(conn, key, message) do - persist(conn, put_in(get(conn), [key], message)) + messages = [message | get_all(conn, key)] + persist(conn, put_in(get(conn), [key], messages)) end @doc """ @@ -69,7 +70,28 @@ defmodule Phoenix.Controller.Flash do """ def get(conn), do: get_session(conn, :phoenix_messages) || %{} def get(conn, key) do - get_in get(conn), [key] + case get_in get(conn), [key] do + nil -> nil + [message | _messages] -> message + end + end + + @doc """ + Returns a list of messages from the Flash + + ## Examples + + iex> conn + iex> |> Flash.put(:notice, "Hello") + iex> |> Flash.put(:notice, "Hi!") + iex> |> Flash.get + %{notice: ["hello", "world"] + + """ + def get_all(conn), do: get_session(conn, :phoenix_messages) || %{} + def get_all(conn, key) do + messages = get_in(get(conn), [key]) || [] + Enum.reverse messages end @doc """ @@ -91,6 +113,27 @@ defmodule Phoenix.Controller.Flash do {message, conn} end + @doc """ + Removes all messages from the Flash, returning a {messages, conn} pair + + ## Examples + + iex> %Conn{} + iex> |> Flash.put(:notices, "oh noes!") + iex> |> Flash.put(:notice, "false alarm!") + iex> |> Flash.pop_all(:notices) |> elem(0) + ["oh noes!", "false alarm!"] + + """ + def pop_all(conn, key) do + messages = get_all(conn, key) + if messages != [] do + conn = persist(conn, Dict.drop(get(conn), [key])) + end + + {messages, conn} + end + @doc """ Clears all flash messages """ diff --git a/test/phoenix/controller/flash_test.exs b/test/phoenix/controller/flash_test.exs index 2bf754f385..8d4e969ade 100644 --- a/test/phoenix/controller/flash_test.exs +++ b/test/phoenix/controller/flash_test.exs @@ -57,7 +57,7 @@ defmodule Phoenix.Controller.FlashTest do test "get/1 returns the map of messages" do conn = conn_with_session |> Flash.put(:notice, "hi") - assert Flash.get(conn) == %{notice: "hi"} + assert Flash.get(conn) == %{notice: ["hi"]} end test "get/2 returns the message by key" do @@ -65,11 +65,31 @@ defmodule Phoenix.Controller.FlashTest do assert Flash.get(conn, :notice) == "hi" end + test "get/2 returns the only the last message put" do + conn = conn_with_session + |> Flash.put(:notice, "hi") + |> Flash.put(:notice, "bye") + assert Flash.get(conn, :notice) == "bye" + end + test "get/2 returns nil for missing key" do conn = conn_with_session assert Flash.get(conn, :notice) == nil end + test "get_all/2 returns a list of messages by key" do + conn = conn_with_session + |> Flash.put(:notices, "hello") + |> Flash.put(:notices, "world") + + assert Flash.get_all(conn, :notices) == ["hello", "world"] + end + + test "get_all/2 returns [] for missing key" do + conn = conn_with_session + assert Flash.get_all(conn, :notices) == [] + end + test "put/3 adds the key/message pair to the flash" do conn = conn_with_session |> Flash.put(:error, "oh noes!") @@ -96,11 +116,21 @@ defmodule Phoenix.Controller.FlashTest do {message, conn} = Flash.pop(conn, :error) assert message == "oh noes!" - assert Flash.get(conn) == %{notice: "false alarm!"} + assert Flash.get(conn) == %{notice: ["false alarm!"]} {message, conn} = Flash.pop(conn, :notice) assert message == "false alarm!" assert Flash.get(conn) == %{} end + + test "pop_all/3 pops all messages from the flash" do + conn = conn_with_session + |> Flash.put(:notices, "oh noes!") + |> Flash.put(:notices, "false alarm!") + + {messages, conn} = Flash.pop_all(conn, :notices) + assert messages == ["oh noes!", "false alarm!"] + assert Flash.get(conn) == %{} + end end