diff --git a/proca/lib/proca/stage/event.ex b/proca/lib/proca/stage/event.ex index 50c6c565..05490d5c 100644 --- a/proca/lib/proca/stage/event.ex +++ b/proca/lib/proca/stage/event.ex @@ -16,7 +16,7 @@ defmodule Proca.Stage.Event do """ alias Proca.{Confirm, Org, Supporter} alias Proca.Pipes.Connection - import Proca.Stage.Support, only: [camel_case_keys: 1, to_iso8601: 1] + import Proca.Stage.Support, only: [camel_case_keys: 2, to_iso8601: 1] @doc """ Routing key for the event message is two-element topic routing key for confirms (because they have subtype), and one element key for CRUD events. @@ -58,7 +58,7 @@ defmodule Proca.Stage.Event do meta |> put_data(event, record, opts ++ [org_id: org_id]) - |> camel_case_keys() + |> camel_case_keys(ignore: :config) |> Connection.publish(exchange_for(org_id), rkey) end diff --git a/proca/lib/proca/stage/support.ex b/proca/lib/proca/stage/support.ex index f48e5a64..c700daa8 100644 --- a/proca/lib/proca/stage/support.ex +++ b/proca/lib/proca/stage/support.ex @@ -5,7 +5,7 @@ defmodule Proca.Stage.Support do (system) or externally (custom). """ - alias Proca.{Action, Supporter, PublicKey, Contact, Field, Confirm} + alias Proca.{Action, Supporter, Confirm} alias Proca.Repo import Ecto.Query, only: [from: 2] alias Broadway.Message @@ -181,7 +181,10 @@ defmodule Proca.Stage.Support do def stringify_keys(map = %{}) do map - |> Enum.map(fn {k, v} -> {Atom.to_string(k), stringify_keys(v)} end) + |> Enum.map(fn + {k, v} when is_atom(k) -> {Atom.to_string(k), stringify_keys(v)} + {k, v} when is_bitstring(k) -> {k, stringify_keys(v)} + end) |> Enum.into(%{}) end @@ -201,15 +204,23 @@ defmodule Proca.Stage.Support do @doc """ Turn the case of keys in the map to camel case """ - def camel_case_keys(map) when is_map(map) do + def camel_case_keys(map, opts \\ []) + + def camel_case_keys(map, opts) when is_map(map) do + ignored_key = Keyword.get(opts, :ignore) + map |> Enum.map(fn {key, val} -> - {ProperCase.camel_case(key), camel_case_keys(val)} + if key == ignored_key do + {ProperCase.camel_case(key), stringify_keys(val)} + else + {ProperCase.camel_case(key), camel_case_keys(val, opts)} + end end) |> Map.new() end - def camel_case_keys(other), do: other + def camel_case_keys(other, _opts), do: other @doc """ Unpack this AMQP metadata diff --git a/proca/mix.exs b/proca/mix.exs index 0fb879f8..9c61d38b 100644 --- a/proca/mix.exs +++ b/proca/mix.exs @@ -4,7 +4,7 @@ defmodule Proca.MixProject do def project do [ app: :proca, - version: "3.4.5", + version: "3.4.6", elixir: "~> 1.7", elixirc_paths: elixirc_paths(Mix.env()), compilers: [:phoenix, :gettext] ++ Mix.compilers(), diff --git a/proca/test/stage/support_test.exs b/proca/test/stage/support_test.exs new file mode 100644 index 00000000..127e2c15 --- /dev/null +++ b/proca/test/stage/support_test.exs @@ -0,0 +1,52 @@ +defmodule Proca.Stage.SupportTest do + use Proca.DataCase + + import Proca.StoryFactory, only: [red_story: 0] + + alias Proca.Stage.Support + + setup do + red_story() + end + + test "camel_case_keys ignores config", %{ + red_campaign: camp, + red_org: org + } do + org_data = %{ + name: org.name, + title: org.title, + config: %{ + some_field: "value", + replace: %{ + "https://example.com/example-candidats" => "https://url.com/other-candidats" + } + } + } + + camp_data = + camp + |> Map.from_struct() + |> Map.replace(:config, %{some_key: "val"}) + |> Map.take([:id, :name, :external_id, :title, :config, :contact_schema]) + |> Map.put(:org, org_data) + + camelized_map = + camp_data + |> Support.camel_case_keys(ignore: :config) + + assert %{ + "externalId" => _, + "contactSchema" => _, + "title" => _, + "config" => %{"some_key" => _}, + "org" => %{ + "name" => _, + "config" => %{ + "some_field" => _, + "replace" => %{"https://example.com/example-candidats" => _} + } + } + } = camelized_map + end +end