Skip to content

Commit 166b99c

Browse files
authored
Merge pull request #5 from robmckinnon/fix-existing-struct-test
Ensure macro called second time with same fields doesn't redefine struct
2 parents d2f667e + 9c7b635 commit 166b99c

File tree

5 files changed

+43
-26
lines changed

5 files changed

+43
-26
lines changed

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Changelog
2+
3+
## 0.0.2 (2016-08-07)
4+
5+
* Bug Fixes
6+
* When `defmodulestruct/2` macro called a second time with the same fields don't redefine struct
7+
8+
## 0.0.1 (2016-08-01)
9+
10+
* Initial release

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Create Elixir structs from data.
44

55
[![Build Status](https://api.travis-ci.org/robmckinnon/data_morph.svg)](https://travis-ci.org/robmckinnon/data_morph)
66
[![Inline docs](http://inch-ci.org/github/robmckinnon/data_morph.svg)](http://inch-ci.org/github/robmckinnon/data_morph)
7+
[![Hex.pm](https://img.shields.io/hexpm/v/data_morph.svg)](https://hex.pm/packages/data_morph)
78

89
## Documentation
910

@@ -13,14 +14,14 @@ You can view [full DataMorph API documentation on hexdocs](https://hexdocs.pm/da
1314

1415
Add
1516
```elixir
16-
{:data_morph, "~> 0.0.1"}
17+
{:data_morph, "~> 0.0.2"}
1718
```
1819
to your deps in `mix.exs` like so:
1920

2021
```elixir
2122
defp deps do
2223
[
23-
{:data_morph, "~> 0.0.1"}
24+
{:data_morph, "~> 0.0.2"}
2425
]
2526
end
2627
```

lib/data_morph/struct.ex

+16-19
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,23 @@ defmodule DataMorph.Struct do
2424
"""
2525
defmacro defmodulestruct kind, fields do
2626
quote do
27-
value = try do
28-
template = struct unquote(kind)
29-
existing_fields = template |> Map.to_list |> Keyword.keys |> MapSet.new
30-
new_fields = MapSet.new unquote(fields)
31-
32-
if MapSet.equal? existing_fields, new_fields do
33-
{:module, unquote(kind), nil, template}
34-
else
35-
union = MapSet.union(existing_fields, new_fields)
36-
defmodule Module.concat([ unquote(kind) ]) do
37-
defstruct MapSet.to_list(union)
38-
end
39-
end
40-
rescue
41-
UndefinedFunctionError ->
42-
defmodule Module.concat([ unquote(kind) ]) do
43-
defstruct unquote(fields)
44-
end
27+
module = unquote(kind)
28+
fields = unquote(fields)
29+
fields_changeset = try do
30+
existing_fields = (struct(module) |> Map.keys) -- [:__struct__]
31+
unless existing_fields === fields do
32+
MapSet.new(existing_fields)
33+
|> MapSet.union(MapSet.new(fields))
34+
|> MapSet.to_list
35+
end
36+
rescue
37+
UndefinedFunctionError -> fields
38+
end
39+
if fields_changeset do
40+
defmodule Module.concat([module]), do: defstruct fields_changeset
41+
else
42+
{:module, module, nil, struct(module)}
4543
end
46-
value
4744
end
4845
end
4946

mix.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule DataMorph.Mixfile do
22
use Mix.Project
33

4-
@version "0.0.1"
4+
@version "0.0.2"
55

66
def project do
77
[app: :data_morph,

test/data_morph/struct_test.exs

+13-4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,17 @@ defmodule DataMorphStructTest do
99
end
1010

1111
test "defmodulestruct/2 macro defines struct with correct template" do
12-
{:module, _, _, template} = DataMorph.Struct.defmodulestruct(Bar.Foo, [:baz, :boom])
12+
{:module, _, binary, template} = DataMorph.Struct.defmodulestruct(Bar.Foo, [:baz, :boom])
1313
assert Map.to_list(template) == [__struct__: Bar.Foo, baz: nil, boom: nil]
14+
assert is_binary(binary)
15+
end
16+
17+
test "defmodulestruct/2 macro called second time with same field keys doesn't redefine struct" do
18+
DataMorph.Struct.defmodulestruct(Foo.Bar.Foo, [:baz, :boom])
19+
20+
{:module, _, binary, template} = DataMorph.Struct.defmodulestruct(Foo.Bar.Foo, [:baz, :boom])
21+
assert Map.to_list(template) == [__struct__: Foo.Bar.Foo, baz: nil, boom: nil]
22+
assert binary == nil
1423
end
1524

1625
test "defmodulestruct/2 macro called second time with additional new field redefines struct" do
@@ -20,9 +29,9 @@ defmodule DataMorphStructTest do
2029
end
2130

2231
test "defmodulestruct/2 macro called second time without original fields redefines struct leaving original keys in struct" do
23-
DataMorph.Struct.defmodulestruct(Baz.Foo, [:baz, :boom])
24-
{:module, _, _, template} = DataMorph.Struct.defmodulestruct(Baz.Foo, [:bish])
25-
assert Map.to_list(template) == [__struct__: Baz.Foo, baz: nil, bish: nil, boom: nil]
32+
DataMorph.Struct.defmodulestruct(Foo.Baz.Foo, [:baz, :boom])
33+
{:module, _, _, template} = DataMorph.Struct.defmodulestruct(Foo.Baz.Foo, [:bish])
34+
assert Map.to_list(template) == [__struct__: Foo.Baz.Foo, baz: nil, bish: nil, boom: nil]
2635
end
2736

2837
test "redefining struct definition only adds keys to new structs" do

0 commit comments

Comments
 (0)