-
Notifications
You must be signed in to change notification settings - Fork 85
Make &stringify_keys/1 private. #605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make &stringify_keys/1 private. #605
Conversation
joshsmith
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a couple quick comments here. Thanks for doing this, and especially for adding a new (missing) test!
| def stringify_keys(%DateTime{} = val), do: val | ||
| def stringify_keys(map = %{}) do | ||
| defp stringify_keys(nil), do: nil | ||
| defp stringify_keys(%DateTime{} = val), do: val |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may be covered by L20.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not. A module struct matches a map, so without this line here, line 13 would match a %DateTime{} and try to recursively stringify those keys as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if there's an is_struct guard clause, so maybe we could instead change line 13 to when is_map(map) and not is_struct(map), but without something like that, this has to stay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@begedin the bigger point is that we should not ever (I think) be hitting a %DateTime{} – moreover, in both cases these functions simply return the value. They are the same function, strictly speaking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having poked around in http://erlang.org/doc/man/erlang.html#is_atom-1, there pretty definitively isn't an is_struct and nothing jumps out at me as a good stand-in. I agree with @begedin, this needs to stay here for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said, we do not need L11 (stringify_keys(nil)) because that does get picked up by stringify_keys(val), do: val.
lib/code_corps/map_utils.ex
Outdated
| defp stringify_keys([head | rest]), do: [stringify_keys(head) | stringify_keys(rest)] | ||
| # Default | ||
| def stringify_keys(not_a_map), do: not_a_map | ||
| defp stringify_keys(not_a_map), do: not_a_map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could just be renamed from not_a_map to val.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that'll be a LOT clearer.
| use ExUnit.Case, async: true | ||
|
|
||
| import CodeCorps.MapUtils, only: [rename: 3] | ||
| import CodeCorps.MapUtils, only: [rename: 3, keys_to_string: 1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind reordering in alpha order?
|
|
||
| # Goes through a list and stringifies keys of any map member | ||
| defp stringify_keys(nil), do: nil | ||
| defp stringify_keys(%DateTime{} = val), do: val |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my point here was misunderstood.
Doing any of the following is the same as doing fn(val), do: val:
fn(%DateTime{} = val), do: valfn(nil = val), do: valfn(RandomApp.RandomModule = val), do: val
All of these are equivalent if all we're doing is passing along val.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for anyone visiting this thread in the future.
The problem is that
stringify_keys(val) when is_map(val) do
clause needs to go first, in order to match properly against a map at all times.
Our App used to transform large maps which also include DateTime structs. To elixir, a struct is a map, so the code here would try to convert DateTime struct keys recursively, which was causing issues, so we needed a DateTime clause before the map clause.
However, now our code is no longer using DateTime structs within its payloads, so it should be save to remove. We don't need the clause on line 11 anymore.
The clause on line 19 is a duplicate of line 22, so we don't need 19 either.
For discussions sake, I thought about this and I believe we could match against all structs using
defp stringify_keys(%{__struct__: _} = val), do: valon line 11, but I don't think it's necessary for us to do that right now. I believe it's enough to just remove lines 11 and 19 and then merge as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review, guys. @begedin I may revisit this thread for your idea on matching against structs--that's clever!
L19 actually isn't a duplicate of L22--stringify_keys and stringify_key are (somewhat non-obviously) different fns (plural v. singular).
I'll push up a commit dropping L11. LMK if there's further to be done; otherwise I'll rebase against develop, re-push, and move on.
|
@arubis the failures are happening because in |
|
Gotcha. How liable am I to break something else while converting these? For example, if in If that's a decent example of all that needs to happen going forward, it won't be too hard. |
|
Just commenting for team ref, but we discussed on Slack, so addressed now. |
|
Indeed -- see discussion at https://codecorps.slack.com/archives/api/p1483669518000712 if needed. |
9427dfe to
a6b9edb
Compare
|
I've found that it's more than just the tests that are still using it will raise: This happens because StripePlatformCustomerService.update_from_stripe/1 is calling MapUtils.keys_to_string/1 with a %DateTime as argument; My understanding is that the |
a6b9edb to
61a482d
Compare
|
@arubis stripity_stripe has already in the 2.0 branch (which we use) switched off of Removing the method and replacing any instance of That being said, I would agree that it's out of scope of this PR, so I'll approve for merge. I've created issue #623 to continue fixing it there. Feel free to tackle that one if you feel like it. |
begedin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to go. The new issue discovered in stripe_testing can be tackled with #623
|
Thanks @arubis! Looks great. |
Since &keys_to_string/1 is public, also add a test case to coverage for
&stringify_keys/1.
Drop useless `stringify_keys(nil)` case.
Continue intercepting %DateTime{} before it matches %{}
61a482d to
b350ac8
Compare
|
🙌 |
What's in this PR?
Define
MapUtils::stringify_keys/1as private (viadefp) rather than public. No change of functionality.Since
MapUtils::&keys_to_string/1is public and calls&stringify_keys, also add a test case for&keys_to_string/1.References
Fixes #600