I have a Erlang webapp, based on Mochiweb and Mnesia, which consumes and emits JSON. It makes sense to store records in Mnesia; however Mochiweb/Mochijson require data in proplist format. So I end up with a large amount of boilerplate code:
-record(foobar, {name, value}).
record_to_proplist(Record)->
[{name, Record#foobar.name},
{value, Record#foobar.value}].
proplist_to_record(Props)->
#foobar{name=proplists:get_value("name", Props),
value=proplists:get_value("value", Props)}.
Fine with a single small record, a pain with lots of large records. Can anyone suggest a way round all this boilerplate code ? I guess I need some way of inspecting a record's fields dynamically; and since records are a compile-time construct, I'm guessing [assuming it's possible] this means injecting code via a macro ..
Thanks!
You should be able to do something like:
-record(foobar, {name, value}).
-record(foo, {other, fields, 'and', stuff}).
record_to_proplist(#foobar{} = Rec) ->
lists:zip(record_info(fields, foobar), tl(tuple_to_list(Rec)));
record_to_proplist(#foo{} = Rec) ->
lists:zip(record_info(fields, foo), tl(tuple_to_list(Rec))).
Etc.
(Or as a macro (still creating a function though, the version where the macro is ?R2P(Rec, foobar) is just too ugly):
-define(R2P(Record), record_to_proplist(#Record{} = Rec) ->
lists:zip(record_info(fields, Record), tl(tuple_to_list(Rec)))).
?R2P(foobar);
?R2P(foo).
)
It sounds like exprecs is what you're looking for:
http://forum.trapexit.org/viewtopic.php?p=21790
Reading from the description:
The module is a parse transform allowing you to export records. The transform adds accessor functions for instantiating, inspecting and modifying records, without having to introduce compile-time dependencies between modules.
See if this helps.
Using record_info(fields, foobar) it is possible to do something dynamically. record_info however is also a compile time construct so the record name cannot be a variable, so you need one clause for each record you intend to convert.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With