Reputation: 4853
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!
Upvotes: 10
Views: 7891
Reputation: 2612
The link in the accepted answer for this has been long dead.
The short answer is to use exprecs from Ulf Wiger.
exprecs is a parse_transform in uwiger/parse_trans
The article on how this works is archived in the web archive at: http://web.archive.org/web/20130729014934/http://forum.trapexit.org/viewtopic.php?p=21790
Upvotes: 0
Reputation: 31015
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.
Upvotes: 2
Reputation: 1979
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).
)
Upvotes: 24
Reputation: 5327
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.
Upvotes: 2