Browse Source

support for records in regroup tag (close #191).

Andreas Stenius 10 years ago
parent
commit
ad3a5ea189
4 changed files with 40 additions and 17 deletions
  1. 2 0
      NEWS.md
  2. 4 1
      src/erlydtl_beam_compiler.erl
  3. 20 15
      src/erlydtl_runtime.erl
  4. 14 1
      test/erlydtl_test_defs.erl

+ 2 - 0
NEWS.md

@@ -17,3 +17,5 @@ Standards](http://www.gnu.org/prep/standards/html_node/NEWS-File.html#NEWS-File)
 
 * Add missing features to the `cycle` tag (#195) (still missing
   independtly stepping the cycle value).
+
+* Support records in regroup tag (#191).

+ 4 - 1
src/erlydtl_beam_compiler.erl

@@ -1324,7 +1324,10 @@ regroup_ast(ListVariable, GrouperVariable, LocalVarName, TreeWalker) ->
 
     {Id, TreeWalker2} = begin_scope(
                           {[{LocalVarName, LocalVarAst}],
-                           [?Q("_@LocalVarAst = erlydtl_runtime:regroup(_@ListAst, _@regroup)",
+                           [?Q(["_@LocalVarAst = erlydtl_runtime:regroup(",
+                                "  _@ListAst, _@regroup,",
+                                "  [{record_info, _RecordInfo}]",
+                                ")"],
                                [{regroup, regroup_filter(GrouperVariable, [])}])
                            ]},
                           TreeWalker1),

+ 20 - 15
src/erlydtl_runtime.erl

@@ -20,7 +20,7 @@
 
 find_value(Key, Data, Options) when is_atom(Key), is_tuple(Data) ->
     Rec = element(1, Data),
-    Info = proplists:get_value(record_info, Options),
+    Info = proplists:get_value(record_info, Options, []),
     case proplists:get_value(Rec, Info) of
         Fields when is_list(Fields), length(Fields) == size(Data) - 1 ->
             case proplists:get_value(Key, Fields) of
@@ -120,28 +120,33 @@ fetch_value(Key, Data, Options, Default) ->
         Val -> Val
     end.
 
-find_deep_value([Key|Rest],Item) ->
-    case find_value(Key,Item) of
+find_deep_value(Key, Data) ->
+    find_deep_value(Key, Data, []).
+
+find_deep_value([Key|Rest], Item, Opts) ->
+    case find_value(Key, Item, Opts) of
         undefined -> undefined;
-        NewItem -> find_deep_value(Rest,NewItem)
+        NewItem -> find_deep_value(Rest, NewItem, Opts)
     end;
-find_deep_value([],Item) -> Item.
+find_deep_value([], Item, _Opts) -> Item.
 
 regroup(List, Attribute) ->
-    regroup(List, Attribute, []).
+    do_regroup(List, Attribute, [], []).
+
+regroup(List, Attribute, Options) ->
+    do_regroup(List, Attribute, Options, []).
 
-regroup([], _, []) ->
-    [];
-regroup([], _, [[{grouper, LastGrouper}, {list, LastList}]|Acc]) ->
+do_regroup([], _, _, []) -> [];
+do_regroup([], _, _, [[{grouper, LastGrouper}, {list, LastList}]|Acc]) ->
     lists:reverse([[{grouper, LastGrouper}, {list, lists:reverse(LastList)}]|Acc]);
-regroup([Item|Rest], Attribute, []) ->
-    regroup(Rest, Attribute, [[{grouper, find_deep_value(Attribute, Item)}, {list, [Item]}]]);
-regroup([Item|Rest], Attribute, [[{grouper, PrevGrouper}, {list, PrevList}]|Acc]) ->
-    case find_deep_value(Attribute, Item) of
+do_regroup([Item|Rest], Attribute, Options, []) ->
+    do_regroup(Rest, Attribute, Options, [[{grouper, find_deep_value(Attribute, Item, Options)}, {list, [Item]}]]);
+do_regroup([Item|Rest], Attribute, Options, [[{grouper, PrevGrouper}, {list, PrevList}]|Acc]) ->
+    case find_deep_value(Attribute, Item, Options) of
         Value when Value =:= PrevGrouper ->
-            regroup(Rest, Attribute, [[{grouper, PrevGrouper}, {list, [Item|PrevList]}]|Acc]);
+            do_regroup(Rest, Attribute, Options, [[{grouper, PrevGrouper}, {list, [Item|PrevList]}]|Acc]);
         Value ->
-            regroup(Rest, Attribute, [[{grouper, Value}, {list, [Item]}], [{grouper, PrevGrouper}, {list, lists:reverse(PrevList)}]|Acc])
+            do_regroup(Rest, Attribute, Options, [[{grouper, Value}, {list, [Item]}], [{grouper, PrevGrouper}, {list, lists:reverse(PrevList)}]|Acc])
     end.
 
 -spec init_translation(init_translation()) -> none | translate_fun().

+ 14 - 1
test/erlydtl_test_defs.erl

@@ -3,6 +3,7 @@
 -export([tests/0]).
 -include("testrunner.hrl").
 -record(testrec, {foo, bar, baz}).
+-record(person, {first_name, gender}).
 
 %% {Name, DTL, Vars, Output}
 %% {Name, DTL, Vars, RenderOpts, Output}
@@ -1302,7 +1303,19 @@ all_test_defs() ->
         <<"People: {% regroup people by gender as gender_list %}{% for gender in gender_list %}{{ gender.grouper }}\n{% for item in gender.list %}{{ item.first_name }}\n{% endfor %}{% endfor %}Done.">>,
         [{people, [[{first_name, "George"}, {gender, "Male"}], [{first_name, "Bill"}, {gender, "Male"}],
                    [{first_name, "Margaret"}, {gender, "Female"}], [{first_name, "Condi"}, {gender, "Female"}]]}],
-        <<"People: Male\nGeorge\nBill\nFemale\nMargaret\nCondi\nDone.">>}
+        <<"People: Male\nGeorge\nBill\nFemale\nMargaret\nCondi\nDone.">>},
+       #test{
+          title = "regroup record",
+          source = <<"{% regroup people by gender as gender_list %}{% for gender in gender_list %}{{ gender.grouper }}:\n{% for person in gender.list %} - {{ person.first_name }}\n{% endfor %}{% endfor %}">>,
+          compile_opts = [{record_info, [{person, record_info(fields, person)}]} | (#test{})#test.compile_opts],
+          render_vars = [{people, [#person{ first_name = "George", gender = "Male" },
+                                   #person{ first_name = "Bill", gender = "Male" },
+                                   #person{ first_name = "Margaret", gender = "Female" },
+                                   #person{ first_name = "Condi", gender = "Female" }
+                                  ]}
+                        ],
+          output = <<"Male:\n - George\n - Bill\nFemale:\n - Margaret\n - Condi\n">>
+         }
       ]},
      {"spaceless",
       [{"Beginning", <<"{% spaceless %}    <b>foo</b>{% endspaceless %}">>, [], <<"<b>foo</b>">>},