tags:

views:

65

answers:

3

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!

+1  A: 

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.

Lukas
+1  A: 

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).

)

Daniel Luna
Nice, but I still have to generate record_to_proplist for each record. Think the right way is probably to code- generated this stuff.
Justin
You could find all records in your project with "find . -name "*rl" -exec grep -- '-record(' {} \; | sed 's/-record(\([^,]*\),.*/\1/'" and auto generate a file based on that.
Daniel Luna
A: 

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.

Roberto Aloi