Sorry

This feed does not validate.

In addition, interoperability with the widest range of feed readers could be improved by implementing the following recommendation.

Source: http://www.planet-im.com/rss20.xml

  1. <?xml version="1.0"?>
  2. <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  3.  
  4. <channel>
  5. <title>Planet IM</title>
  6. <link>http://planet-im.com/</link>
  7. <language>en</language>
  8. <description>Planet IM - http://planet-im.com/</description>
  9.  
  10. <item>
  11. <title>Justin Kirby: exprecs, making json usable.</title>
  12. <guid>http://blogs.openaether.org/?p=253</guid>
  13. <link>http://blogs.openaether.org/?p=253</link>
  14. <description>&lt;div id=&quot;outline-container-1&quot; class=&quot;outline-2&quot;&gt;
  15. &lt;h2 id=&quot;sec-1&quot;&gt;Erlang and Syntax&lt;/h2&gt;
  16. &lt;div class=&quot;outline-text-2&quot; id=&quot;text-1&quot;&gt;
  17. &lt;p&gt; Many flames have been ignited over erlang&amp;#8217;s syntax. Erlang as a system is exceptional; easy concurrency, clustering and OTP design principles to name just a few. However, its syntax has a lot to be desired. &lt;/p&gt;
  18. &lt;p&gt; There are minor annoyances, like the comma (&amp;#8220;,&amp;#8221;), period (&amp;#8220;.&amp;#8221;) and semicolon (&amp;#8220;;&amp;#8221;), which make diffs larger and harder to read than they should be, and cause irritating compile errors after a quick edit. &lt;/p&gt;
  19. &lt;p&gt; A simple contrived example: &lt;/p&gt;
  20. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;add&lt;/span&gt;(&lt;span&gt;First&lt;/span&gt;, &lt;span&gt;Second&lt;/span&gt;) -&amp;gt;
  21.    &lt;span&gt;Result&lt;/span&gt; = &lt;span&gt;First&lt;/span&gt; + &lt;span&gt;Second&lt;/span&gt;.
  22. &lt;/pre&gt;
  23. &lt;p&gt; Now if you want to store the result &lt;/p&gt;
  24. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;add&lt;/span&gt;(&lt;span&gt;First&lt;/span&gt;, &lt;span&gt;Second&lt;/span&gt;) -&amp;gt;
  25.    &lt;span&gt;Result&lt;/span&gt; = &lt;span&gt;First&lt;/span&gt; + &lt;span&gt;Second&lt;/span&gt;,
  26.    &lt;span&gt;store_and_return&lt;/span&gt;(&lt;span&gt;Result&lt;/span&gt;).
  27. &lt;/pre&gt;
  28. &lt;p&gt; And now there is a two line diff, instead of one: &lt;/p&gt;
  29. &lt;pre class=&quot;src src-diff&quot;&gt;&lt;span&gt;--- &lt;/span&gt;&lt;span&gt;add1.erl    2011-09-20 11:19:18.000000000 -0400&lt;/span&gt;&lt;span&gt;
  30. +++ &lt;/span&gt;&lt;span&gt;add2.erl    2011-09-20 11:20:34.000000000 -0400&lt;/span&gt;&lt;span&gt;
  31. &lt;/span&gt;&lt;span&gt;@@ -1,2 +1,3 @@&lt;/span&gt;
  32. &lt;span&gt; add(First,Second) -&amp;gt;
  33. &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;    Result = First + Second.
  34. &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;    Result = First + Second,
  35. &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;    store_and_return(Result).
  36. &lt;/span&gt;&lt;/pre&gt;
  37. &lt;p&gt; This is a minor nuisance, but the number of times I have forgotten to change a period to a comma approaches infinity. &lt;/p&gt;
  38. &lt;/div&gt;&lt;/div&gt;
  39. &lt;div id=&quot;outline-container-1_1&quot; class=&quot;outline-3&quot;&gt;
  40. &lt;h3 id=&quot;sec-1_1&quot;&gt;Records&lt;/h3&gt;
  41. &lt;div class=&quot;outline-text-3&quot; id=&quot;text-1_1&quot;&gt;
  42. &lt;p&gt; While I lack a rigorous statistical analysis, you would be hard pressed to find an erlang programmer who enjoys records. Records are essentially syntactic sugar on top of tagged tuples. This sugar does not taste good. &lt;/p&gt;
  43. &lt;p&gt; Defining records is easy and straight forward: &lt;/p&gt;
  44. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;-record&lt;/span&gt;(&lt;span&gt;poetry&lt;/span&gt;, {
  45.          style  :: &lt;span&gt;string&lt;/span&gt;(),
  46.          line   :: &lt;span&gt;string&lt;/span&gt;(),
  47.          author :: &lt;span&gt;string&lt;/span&gt;()
  48.          }).
  49. &lt;/pre&gt;
  50. &lt;p&gt; However, using them is another story. &lt;/p&gt;
  51. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;vogon_example&lt;/span&gt;() -&amp;gt;
  52.    #&lt;span&gt;poetry&lt;/span&gt;{style = &lt;span&gt;&quot;vogon&quot;&lt;/span&gt;,
  53.            line = &lt;span&gt;&quot;Oh freddled gruntbuggly/thy micturations are to me/As plurdled gabbleblotchits on a lurgid bee.&quot;&lt;/span&gt;,
  54.            author = &lt;span&gt;&quot;Jeltz&quot;&lt;/span&gt;
  55.            }.
  56.  
  57. &lt;span&gt;echo_poem&lt;/span&gt;(&lt;span&gt;Poem&lt;/span&gt; = #&lt;span&gt;poetry&lt;/span&gt;{}) -&amp;gt;
  58.    &lt;span&gt;io&lt;/span&gt;:&lt;span&gt;format&lt;/span&gt;(&lt;span&gt;&quot;~s~nby ~s&quot;&lt;/span&gt;,[&lt;span&gt;Poem&lt;/span&gt;#&lt;span&gt;poetry&lt;/span&gt;.line,&lt;span&gt;Poem&lt;/span&gt;#&lt;span&gt;poetry&lt;/span&gt;.author]).
  59. &lt;/pre&gt;
  60. &lt;p&gt; The need to specify the record type on a variable before using the element accessor can lead to some fairly ugly code &lt;/p&gt;
  61. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;contrived&lt;/span&gt;(&lt;span&gt;Collection&lt;/span&gt;) -&amp;gt;
  62.    %% &lt;span&gt;in R14 you do not need the parens
  63. &lt;/span&gt;    (&lt;span&gt;Collection&lt;/span&gt;#&lt;span&gt;collection&lt;/span&gt;.vogon)#&lt;span&gt;poetry&lt;/span&gt;.author.
  64. &lt;/pre&gt;
  65. &lt;p&gt; If the need to specify the record type was removed you could do &lt;/p&gt;
  66. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;contrived&lt;/span&gt;(&lt;span&gt;Collection&lt;/span&gt;) -&amp;gt;
  67.    &lt;span&gt;Collection&lt;/span&gt;.vogon.author.
  68. &lt;/pre&gt;
  69. &lt;p&gt; Which looks much cleaner. However, ugly syntax is a trivial annoyance and is primarily a subjective aesthetic concern. &lt;/p&gt;
  70. &lt;p&gt; The need to specify the record type is a more pragmatic problem. Writing generic code that consumes records conforming to a pattern or interface is impossible. &lt;/p&gt;
  71. &lt;p&gt; While it is true that erlang:element/2 can be used to access records as tuples, the usability of named fields is lost. If the record definition is changed, your code that uses erlang:element/2 may break in interesting ways. (note: that is not a Good Thing[tm]) &lt;/p&gt;
  72. &lt;/div&gt;&lt;/div&gt;
  73.  
  74.  
  75. &lt;div id=&quot;outline-container-2&quot; class=&quot;outline-2&quot;&gt;
  76. &lt;h2 id=&quot;sec-2&quot;&gt;exprecs to the rescue&lt;/h2&gt;
  77. &lt;div class=&quot;outline-text-2&quot; id=&quot;text-2&quot;&gt;
  78. &lt;p&gt; I stumbled onto an interesting chunk of code by &lt;a href=&quot;http://ulf.wiger.net/weblog/&quot;&gt;Ulf Wiger&lt;/a&gt; called &lt;a href=&quot;http://forum.trapexit.org/viewtopic.php?p=21790&quot;&gt;exprecs&lt;/a&gt;. Exprecs is a parse transform that allows you to work magic, freeing your code from the constraints of the erlang record while still maintaining the benefits derived from named fields. &lt;/p&gt;
  79. &lt;p&gt; At this point it may be beneficial for you to read over the exprecs edoc. To make things simple I have generated the edoc html. &lt;a href=&quot;http://blogs.openaether.org/data/exprecs.html &quot;&gt;Go have a quick read&lt;/a&gt;, I will wait. &lt;/p&gt;
  80. &lt;p&gt; &amp;hellip; &lt;/p&gt;
  81. &lt;p&gt; While it doesn&amp;#8217;t remove the need to scatter # all over your code, exprecs does enable the ability to treat records as discoverable and fungible entities. This opens the door to more generic and reusable code. &lt;/p&gt;
  82. &lt;/div&gt;&lt;/div&gt;
  83. &lt;div id=&quot;outline-container-2_1&quot; class=&quot;outline-3&quot;&gt;
  84. &lt;h3 id=&quot;sec-2_1&quot;&gt;The Problem&lt;/h3&gt;
  85. &lt;div class=&quot;outline-text-3&quot; id=&quot;text-2_1&quot;&gt;
  86. &lt;p&gt;    I have written a lot of erlang code dealing with json, primarily in    REST interfaces built with &lt;a href=&quot;http://webmachine.basho.com/&quot;&gt;webmachine&lt;/a&gt;. The json validation and    parsing into erlang terms is made extremely easy thanks to    &lt;a href=&quot;https://github.com/mochi/MochiWeb&quot;&gt;mochijson2&lt;/a&gt;. mochijson2 has a lot of benefits: roundtrips are    consistent, json strings are parsed to erlang binaries and a single    line of code is generally all you need. &lt;/p&gt;
  87. &lt;p&gt;    However, I do find the resulting erlang terms produced by    mochijson2 to be confusing and difficult to remember. Recursing    down a proplist tree is not my most favorite activity and one can    easily get lost in large data structures. This makes changing the    data structure difficult, error prone and tedious, even with good    unit tests. &lt;/p&gt;
  88. &lt;p&gt;    The appropriate representation of large or complex data structures    in erlang is a record. Due to the problems outlined above,    abstracting out the mochijson2 code to create a generic json to    record parser is impossible. &lt;/p&gt;
  89. &lt;p&gt;    This means that I found myself writing json to record parsers    frequently. I was violating DRY and becoming more and more    frustrated. &lt;/p&gt;
  90. &lt;/div&gt;&lt;/div&gt;
  91.  
  92. &lt;div id=&quot;outline-container-2_2&quot; class=&quot;outline-3&quot;&gt;
  93. &lt;h3 id=&quot;sec-2_2&quot;&gt;The Solution&lt;/h3&gt;
  94. &lt;div class=&quot;outline-text-3&quot; id=&quot;text-2_2&quot;&gt;
  95. &lt;p&gt;    Thanks to the awesomeness that is exprecs, I was able to write a    module that would take the erlang terms produced by    mochijson2:decode/1 and transform them into a record. The code can    even roundtrip from a record to json. &lt;/p&gt;
  96. &lt;p&gt;    I no longer have to write yet another proplist walker in order to    get json into mnesia. I am quite excited about this. &lt;/p&gt;
  97. &lt;p&gt;    The json_rec.erl module exports two functions; to_rec/3 and    to_json/2. The following code is example usage to illustrate the    interface: &lt;/p&gt;
  98. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;store_vogon_json&lt;/span&gt;(&lt;span&gt;HttpBody&lt;/span&gt;) -&amp;gt;
  99.    &lt;span&gt;Json&lt;/span&gt; = &lt;span&gt;mochijson2&lt;/span&gt;:&lt;span&gt;decode&lt;/span&gt;(&lt;span&gt;HttpBody&lt;/span&gt;),
  100.    &lt;span&gt;Record&lt;/span&gt; = &lt;span&gt;json_rec&lt;/span&gt;:&lt;span&gt;to_rec&lt;/span&gt;(&lt;span&gt;Json&lt;/span&gt;, vogon_model, &lt;span&gt;vogon_model&lt;/span&gt;:&lt;span&gt;new&lt;/span&gt;(&amp;lt;&amp;lt;&lt;span&gt;&quot;poetry&quot;&lt;/span&gt;&amp;gt;&amp;gt;)),
  101.    &lt;span&gt;vogon_model&lt;/span&gt;:&lt;span&gt;create&lt;/span&gt;(&lt;span&gt;Record&lt;/span&gt;).
  102.  
  103. &lt;span&gt;get_vogon&lt;/span&gt;(&lt;span&gt;Author&lt;/span&gt;) -&amp;gt;
  104.    &lt;span&gt;Record&lt;/span&gt; = &lt;span&gt;vogon_model&lt;/span&gt;:&lt;span&gt;read&lt;/span&gt;(&lt;span&gt;Author&lt;/span&gt;),
  105.    &lt;span&gt;json_rec&lt;/span&gt;:&lt;span&gt;to_json&lt;/span&gt;(&lt;span&gt;Record&lt;/span&gt;, vogon_model).
  106. &lt;/pre&gt;&lt;/div&gt;
  107. &lt;/div&gt;
  108. &lt;div id=&quot;outline-container-2_3&quot; class=&quot;outline-3&quot;&gt;
  109. &lt;h3 id=&quot;sec-2_3&quot;&gt;exprecs Explained&lt;/h3&gt;
  110. &lt;div class=&quot;outline-text-3&quot; id=&quot;text-2_3&quot;&gt;
  111. &lt;p&gt;    In order to give some example usage of exprecs, I am going to provide    lots of contrived examples. If you want a real world use case, see    the code for json_rec. &lt;/p&gt;
  112. &lt;p&gt;    We have two modules, poetry.erl and book.erl that each have their    own record defined in poetry.hrl and book.hrl &lt;/p&gt;
  113. &lt;pre class=&quot;src src-erlang&quot;&gt;%% &lt;span&gt;include/poetry.hrl
  114. &lt;/span&gt;&lt;span&gt;-record&lt;/span&gt;(&lt;span&gt;poetry&lt;/span&gt;, {
  115.          style      :: &lt;span&gt;atom&lt;/span&gt;(),
  116.          excerpt    :: &lt;span&gt;string&lt;/span&gt;(),
  117.          author     :: &lt;span&gt;string&lt;/span&gt;(),
  118.          available  :: &lt;span&gt;boolean&lt;/span&gt;(),
  119.          count      :: &lt;span&gt;integer&lt;/span&gt;()
  120.         }).
  121.  
  122. %% &lt;span&gt;include/book.hrl
  123. &lt;/span&gt;&lt;span&gt;-record&lt;/span&gt;(&lt;span&gt;book&lt;/span&gt;, {
  124.          style      :: &lt;span&gt;atom&lt;/span&gt;(),
  125.          count      :: &lt;span&gt;integer&lt;/span&gt;(),
  126.          available  :: &lt;span&gt;boolean&lt;/span&gt;(),
  127.          pages      :: &lt;span&gt;integer&lt;/span&gt;(),
  128.          excerpt    :: &lt;span&gt;string&lt;/span&gt;(),
  129.          author     :: &lt;span&gt;string&lt;/span&gt;()
  130.         }).
  131. &lt;/pre&gt;
  132. &lt;p&gt;    Now you have a massive inefficient database of 100 book records and    100 poetry records. Someone has just snuck in and stolen your entire    library and you are pedantic enough to want to update this fact. &lt;/p&gt;
  133. &lt;p&gt;    Since the two records have an different number of fields and they    are in a different order, using element/2 is not an option. This is    where exprecs comes in. &lt;/p&gt;
  134. &lt;/div&gt;&lt;/div&gt;
  135. &lt;div id=&quot;outline-container-2_3_1&quot; class=&quot;outline-4&quot;&gt;
  136. &lt;h4 id=&quot;sec-2_3_1&quot;&gt;Housekeeping&lt;/h4&gt;
  137. &lt;div class=&quot;outline-text-4&quot; id=&quot;text-2_3_1&quot;&gt;
  138. &lt;p&gt;     First some basic housekeeping. The record needs to be &amp;#8216;exported&amp;#8217;     from a module &lt;/p&gt;
  139. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;-module&lt;/span&gt;(poetry).
  140.  
  141. %% &lt;span&gt;include the record definition or put it inline
  142. &lt;/span&gt;&lt;span&gt;-include&lt;/span&gt;(&lt;span&gt;&quot;poetry.hrl&quot;&lt;/span&gt;).
  143.  
  144. &lt;span&gt;-compile&lt;/span&gt;({parse_transform, exprecs}).
  145. &lt;span&gt;-export_records&lt;/span&gt;([poetry]).
  146. &lt;/pre&gt;
  147. &lt;p&gt;     To make the above &lt;code&gt;-compile&lt;/code&gt; work, exprecs.erl needs to be in your     erlang path. For simplicity I have put exprecs.erl in a basic     erlang app that all our erlang projects depend on, that way I am     certain to have it available. ( I need a better way to do this     besides having a &amp;#8216;utils&amp;#8217;/'misc&amp;#8217; app.) &lt;/p&gt;
  148. &lt;p&gt;     &lt;code&gt;-export_records&lt;/code&gt; is created by the exprecs parse transform. This is      what generates and exports the funky &amp;#8216;#get-&amp;#8217; functions and makes      the records usable. &lt;/p&gt;
  149. &lt;p&gt;     ..and the same for the book.erl module &lt;/p&gt;
  150. &lt;/div&gt;&lt;/div&gt;
  151.  
  152. &lt;div id=&quot;outline-container-2_3_2&quot; class=&quot;outline-4&quot;&gt;
  153. &lt;h4 id=&quot;sec-2_3_2&quot;&gt;update function&lt;/h4&gt;
  154. &lt;div class=&quot;outline-text-4&quot; id=&quot;text-2_3_2&quot;&gt;
  155. &lt;p&gt;    Now we need to write a function that updates the count field to     zero in all records, since our collection has been stolen. &lt;/p&gt;
  156. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;-type&lt;/span&gt; &lt;span&gt;count_record&lt;/span&gt;() :: #&lt;span&gt;poetry&lt;/span&gt;{} | #&lt;span&gt;book&lt;/span&gt;{}.
  157. &lt;span&gt;-spec&lt;/span&gt; &lt;span&gt;reset_count&lt;/span&gt;(&lt;span&gt;Module&lt;/span&gt; :: &lt;span&gt;atom&lt;/span&gt;(), &lt;span&gt;Record&lt;/span&gt; :: &lt;span&gt;count_record&lt;/span&gt;() ) -&amp;gt;
  158.                                   {error, &lt;span&gt;string&lt;/span&gt;()} | {ok, &lt;span&gt;count_record&lt;/span&gt;()}.
  159. &lt;span&gt;reset_count&lt;/span&gt;(&lt;span&gt;Module&lt;/span&gt;, &lt;span&gt;Record&lt;/span&gt;) -&amp;gt;
  160.    %% &lt;span&gt;crash if there is not a count field
  161. &lt;/span&gt;    true = &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;member&lt;/span&gt;(count, &lt;span&gt;Module&lt;/span&gt;:&lt;span&gt;'#info-'&lt;/span&gt;(fields,&lt;span&gt;Record&lt;/span&gt;)),
  162.  
  163.    %% &lt;span&gt;get the count value by specifying the field we want. notice how
  164. &lt;/span&gt;    %% &lt;span&gt;there is no explicit mention of what record is being used. We
  165. &lt;/span&gt;    %% &lt;span&gt;just care that there is a count.
  166. &lt;/span&gt;    &lt;span&gt;case&lt;/span&gt; &lt;span&gt;Module&lt;/span&gt;:&lt;span&gt;'#get-'&lt;/span&gt;(count, &lt;span&gt;Record&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
  167.        0 -&amp;gt;
  168.            &lt;span&gt;Record&lt;/span&gt;;
  169.        &lt;span&gt;_N&lt;/span&gt; -&amp;gt;
  170.            &lt;span&gt;Module&lt;/span&gt;:&lt;span&gt;'#set-'&lt;/span&gt;([{count, 0}, {available, false}], &lt;span&gt;Record&lt;/span&gt;)
  171.    &lt;span&gt;end&lt;/span&gt;.
  172. &lt;/pre&gt;
  173. &lt;p&gt;     In order to use this we write a simple loop over all books and     poetry available, specifying the module and record. &lt;/p&gt;
  174. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;reset_all&lt;/span&gt;() -&amp;gt;
  175.    %% &lt;span&gt;loop over all modules
  176. &lt;/span&gt;    &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;foreach&lt;/span&gt;(&lt;span&gt;fun&lt;/span&gt;(&lt;span&gt;Module&lt;/span&gt;) -&amp;gt;
  177.                          %% &lt;span&gt;reset the count of all records in the module
  178. &lt;/span&gt;                          &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;foreach&lt;/span&gt;(&lt;span&gt;fun&lt;/span&gt;(&lt;span&gt;Record&lt;/span&gt;) -&amp;gt;
  179.                                                &lt;span&gt;New&lt;/span&gt; = &lt;span&gt;reset_count&lt;/span&gt;(&lt;span&gt;Module&lt;/span&gt;, &lt;span&gt;Record&lt;/span&gt;),
  180.                                                &lt;span&gt;Module&lt;/span&gt;:&lt;span&gt;update&lt;/span&gt;(&lt;span&gt;New&lt;/span&gt;)
  181.                                        &lt;span&gt;end&lt;/span&gt;, &lt;span&gt;Module&lt;/span&gt;:&lt;span&gt;all&lt;/span&gt;())
  182.                  &lt;span&gt;end&lt;/span&gt;, [poetry, book]).
  183. &lt;/pre&gt;
  184. &lt;p&gt;     The bane of all example code is that bad code can be easier to     read. I hope the above illustrates the benefit of exprecs, namely,     that it opens the door to generic record-based code. &lt;/p&gt;
  185. &lt;/div&gt;&lt;/div&gt;
  186.  
  187.  
  188.  
  189. &lt;div id=&quot;outline-container-3&quot; class=&quot;outline-2&quot;&gt;
  190. &lt;h2 id=&quot;sec-3&quot;&gt;json_rec, a walk through&lt;/h2&gt;
  191. &lt;div class=&quot;outline-text-2&quot; id=&quot;text-3&quot;&gt;
  192. &lt;p&gt;   As with all code, there are quite few bits missing, namely internal   documentation. It may prove difficult for others to hack on this   until I get to that. The good news is that I have extensively   documented the exported functions and even written an example model. &lt;/p&gt;
  193. &lt;p&gt;   You can pull the current code from   &lt;a href=&quot;https://github.com/justinkirby/json_rec&quot;&gt;https://github.com/justinkirby/json_rec&lt;/a&gt; &lt;/p&gt;
  194. &lt;/div&gt;&lt;/div&gt;
  195. &lt;div id=&quot;outline-container-3_1&quot; class=&quot;outline-3&quot;&gt;
  196. &lt;h3 id=&quot;sec-3_1&quot;&gt;Using&lt;/h3&gt;
  197. &lt;div class=&quot;outline-text-3&quot; id=&quot;text-3_1&quot;&gt;
  198. &lt;p&gt;    The goal of json_rec is to take json and provide a record    ultimately destined for some type of datastore; mnesia, riak,    couch, etc..  As such json_rec assumes that you have a model for    interacting with the store, e.g. standard MVC. &lt;/p&gt;
  199. &lt;p&gt;    json_rec places a few very simple requirements on your model&amp;#8217;s    interface: &lt;/p&gt;
  200. &lt;ul&gt;
  201. &lt;li&gt;it MUST export new/1 &lt;/li&gt;
  202. &lt;li&gt;it MUST export rec/1 &lt;/li&gt;
  203. &lt;li&gt;it MUST export the exprecs transforms or the record. &lt;/li&gt;
  204. &lt;/ul&gt;
  205. &lt;p&gt;    At this point, if you have not read the exprecs &lt;a href=&quot;http://blogs.openaether.org/data/exprecs.html&quot;&gt;edoc&lt;/a&gt; I highly    recommend that you do. &lt;/p&gt;
  206. &lt;p&gt;    Keeping with the above example, let&amp;#8217;s make book.erl a json_rec    compatible module. &lt;/p&gt;
  207. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;-module&lt;/span&gt;(book).
  208.  
  209. &lt;span&gt;-export&lt;/span&gt;([
  210.         &lt;span&gt;new/1&lt;/span&gt;,
  211.         &lt;span&gt;rec/1&lt;/span&gt;
  212.        ]).
  213.  
  214. &lt;span&gt;-record&lt;/span&gt;(&lt;span&gt;book&lt;/span&gt;, {
  215.          style      :: &lt;span&gt;atom&lt;/span&gt;(),
  216.          count      :: &lt;span&gt;integer&lt;/span&gt;(),
  217.          available  :: &lt;span&gt;boolean&lt;/span&gt;(),
  218.          pages      :: &lt;span&gt;integer&lt;/span&gt;(),
  219.          excerpt    :: &lt;span&gt;string&lt;/span&gt;(),
  220.          author     :: &lt;span&gt;string&lt;/span&gt;()
  221.         }).
  222.  
  223. %% &lt;span&gt;the exprecs export of the record interface
  224. &lt;/span&gt;&lt;span&gt;-compile&lt;/span&gt;({parse_transform, exprecs}).
  225. &lt;span&gt;-export_records&lt;/span&gt;([book]).
  226.  
  227. %% &lt;span&gt;here we provide a mapping of the json key to a record.
  228. &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;(&amp;lt;&amp;lt;&lt;span&gt;&quot;book&quot;&lt;/span&gt;&amp;gt;&amp;gt;) -&amp;gt;
  229.    &lt;span&gt;'#new-book'&lt;/span&gt;();
  230.  
  231. %% &lt;span&gt;if the key is unknown, return undefined.
  232. &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;(&lt;span&gt;_RecName&lt;/span&gt;) -&amp;gt;
  233.    undefined.
  234.  
  235. %% &lt;span&gt;return true for the #book{} indicating that we support it.
  236. &lt;/span&gt;&lt;span&gt;rec&lt;/span&gt;(#&lt;span&gt;book&lt;/span&gt;{}) -&amp;gt;&lt;span&gt; &lt;/span&gt;true;
  237. &lt;span&gt;rec&lt;/span&gt;(&lt;span&gt;_&lt;/span&gt;) -&amp;gt;&lt;span&gt; &lt;/span&gt;false.
  238. &lt;/pre&gt;
  239. &lt;p&gt;    At this point we can take the following json and transform it into the #book{} record. &lt;/p&gt;
  240. &lt;pre class=&quot;src src-javascript&quot;&gt;{
  241.    &lt;span&gt;&quot;style&quot;&lt;/span&gt;: &lt;span&gt;&quot;fiction&quot;&lt;/span&gt;,
  242.    &lt;span&gt;&quot;count&quot;&lt;/span&gt;: 1,
  243.    &lt;span&gt;&quot;available&quot;&lt;/span&gt;: &lt;span&gt;true&lt;/span&gt;,
  244.    &lt;span&gt;&quot;pages&quot;&lt;/span&gt;: 42,
  245.    &lt;span&gt;&quot;excerpt&quot;&lt;/span&gt;: &lt;span&gt;&quot;Good bye and thanks for all the fish.&quot;&lt;/span&gt;,
  246.    &lt;span&gt;&quot;author&quot;&lt;/span&gt;:&lt;span&gt;&quot;Adams, Douglas&quot;&lt;/span&gt;
  247. }
  248. &lt;/pre&gt;
  249. &lt;p&gt;    We can get a #book{} record from the above with &lt;/p&gt;
  250. &lt;pre class=&quot;src src-erlang&quot;&gt;&lt;span&gt;-spec&lt;/span&gt; &lt;span&gt;json_to_rec&lt;/span&gt;(&lt;span&gt;Json&lt;/span&gt; :: &lt;span&gt;string&lt;/span&gt;()) -&amp;gt;&lt;span&gt; &lt;/span&gt;#&lt;span&gt;book&lt;/span&gt;{}.
  251. &lt;span&gt;json_to_rec&lt;/span&gt;(&lt;span&gt;Json&lt;/span&gt;) -&amp;gt;
  252.    &lt;span&gt;ErlJson&lt;/span&gt; = &lt;span&gt;mochijson2&lt;/span&gt;:&lt;span&gt;decode&lt;/span&gt;(&lt;span&gt;Json&lt;/span&gt;),
  253.    &lt;span&gt;Record&lt;/span&gt; = &lt;span&gt;book&lt;/span&gt;:&lt;span&gt;new&lt;/span&gt;(&amp;lt;&amp;lt;&lt;span&gt;&quot;book&quot;&lt;/span&gt;&amp;gt;&amp;gt;),
  254.    &lt;span&gt;json_rec&lt;/span&gt;:&lt;span&gt;to_rec&lt;/span&gt;(&lt;span&gt;ErlJson&lt;/span&gt;, book, &lt;span&gt;Record&lt;/span&gt;).
  255. &lt;/pre&gt;
  256. &lt;/div&gt;&lt;/div&gt;
  257.  
  258. &lt;div id=&quot;outline-container-3_2&quot; class=&quot;outline-3&quot;&gt;
  259. &lt;h3 id=&quot;sec-3_2&quot;&gt;Other features&lt;/h3&gt;
  260. &lt;div class=&quot;outline-text-3&quot; id=&quot;text-3_2&quot;&gt;
  261. &lt;p&gt;    json_rec will try its best to transform into known records,    e.g. ones exported from the module. However, if Module:new/1    returns &amp;#8216;undefined&amp;#8217;, then it will fall back to a proplist. The    major downside of this is that it loses the clean round trip that    mochijson2 gives you. &lt;/p&gt;
  262. &lt;p&gt;    json_rec also supports nested records. Whenever a json dictionary    key has a dictionary as a value json_rec will call Module:new/1 to    determine if it is a known record type. If it is json_rec will    create a record and make it the value of the parent record field. &lt;/p&gt;
  263. &lt;p&gt;    json_rec supports a list of dictionaries as well. &lt;/p&gt;
  264. &lt;p&gt;    In summary I have tried to support all reasonable data structure    combinations. json_rec does a best effort to do what you    expect. However, it is not an AI or Turing-complete so I am sure    there are various combinations of lists and dicts that will not    work. &lt;/p&gt;
  265. &lt;/div&gt;&lt;/div&gt;
  266.  
  267. &lt;div id=&quot;outline-container-3_3&quot; class=&quot;outline-3&quot;&gt;
  268. &lt;h3 id=&quot;sec-3_3&quot;&gt;Summary&lt;/h3&gt;
  269. &lt;div class=&quot;outline-text-3&quot; id=&quot;text-3_3&quot;&gt;
  270. &lt;p&gt;    json_rec is an 80% solution that has saved me a ton of copy/paste    coding. I have found it extremely useful in saving my sanity when    transforming json into useable data. &lt;/p&gt;
  271. &lt;p&gt;    I would like to thank Ulf Wiger for creating exprecs, making    json_rec possible. &lt;/p&gt;
  272. &lt;/div&gt;&lt;/div&gt;
  273.  
  274.  
  275.  
  276. &lt;p&gt;   &lt;/p&gt;</description>
  277. <pubDate>Tue, 08 Nov 2011 15:20:24 +0000</pubDate>
  278. </item>
  279. <item>
  280. <title>Artur Hefczyc: Tigase Command Line Management Tool announcement</title>
  281. <guid>http://www.tigase.org/3037 at http://www.tigase.org</guid>
  282. <link>http://www.tigase.org/content/tigase-command-line-management-tool-announcement</link>
  283. <description>&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://projects.tigase.org/projects/tclmt&quot;&gt;TCLMT&lt;/a&gt;&lt;/strong&gt; is new utility to manage XMPP servers by execution of ad-hoc commands. It's designed to be simple and powerful in use and work in two modes:&lt;/p&gt;
  284. &lt;ul&gt;
  285. &lt;li&gt;non interactive&lt;/li&gt;
  286. &lt;li&gt;interactive&lt;/li&gt;
  287. &lt;/ul&gt;
  288. &lt;p&gt;Currently it partially supports ad-hoc commands which are specified in &lt;a href=&quot;http://xmpp.org/extensions/xep-0133.html&quot;&gt;XEP-0133 Service Administration&lt;/a&gt; and implemented by Tigase XMPP Server. As for it contains support for:&lt;/p&gt;
  289. &lt;ul&gt;
  290. &lt;li&gt;4.1.   Add user&lt;/li&gt;
  291. &lt;li&gt;4.2.   Delete user&lt;/li&gt;
  292. &lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;http://www.tigase.org/content/tigase-command-line-management-tool-announcement&quot; target=&quot;_blank&quot;&gt;read more&lt;/a&gt;&lt;/p&gt;</description>
  293. <pubDate>Wed, 02 Nov 2011 20:28:58 +0000</pubDate>
  294. </item>
  295. <item>
  296. <title>Process One: hosted.IM: user authentication against your company database</title>
  297. <guid>tag:process-one.net,2011:en/blogs/3.4821</guid>
  298. <link>http://www.process-one.net/en/blogs/article/hosted.im_user_authentication_against_your_company_database/</link>
  299. <description>&lt;p&gt;Hosting.IM, the leading Cloud-based Instant Messaging service by ProcessOne, has extended further its user management integration features for larger companies. Please read about this new service below.&lt;/p&gt; &lt;p&gt;A common feature requested by many hosted.IM customers is the ability to authenticate users according to a pre-existent company database. Since then, we have implemented the possibility to authenticate against your POP3 or IMAP server. However it requires that your instant messaging domain name matches the domain from your e-mail addresses.&lt;/p&gt;
  300.  
  301. &lt;p&gt;Several companies already have an intranet authentication backend, like LDAP, Active Directory or an Ad-Hoc database. On the other hand our experience with large sized companies is that is not a good idea to expose LDAP or Active Directory to the internet.&lt;/p&gt;
  302.  
  303. &lt;p&gt;To overcome this problematic scenario we have added a new authentication method, which consists on delegating the authentication to an external REST API, acting as a fa├žade to your own intranet database.&lt;/p&gt;
  304.  
  305. &lt;p&gt;The behaviour expected by hosted.IM is fairly straightforward. Your API must answer a GET query with details about the user that is trying to authenticate to your IM domain with 'true' or 'false' depending on whether the user is authorized or not.&lt;/p&gt;
  306.  
  307. &lt;p&gt;In the image below we see how &lt;i&gt;mydomain.com&lt;/i&gt; administrator sets &lt;i&gt;https://mydomain.com/auth&lt;/i&gt; as the REST URL and clicks on the highlighted &lt;i&gt;Verify your service&lt;/i&gt; link to ensure hosted.IM is able to contact it:&lt;/p&gt;
  308. &lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.process-one.net/resources/rest2-492x403.png&quot; alt=&quot;image&quot; width=&quot;492&quot; height=&quot;403&quot; /&gt;&lt;/p&gt;
  309.  
  310. &lt;p&gt;The next step would be to click on the 'Switch' button and that's all!. Now hosted.IM will authenticate users against your company data source.&lt;/p&gt;
  311.  
  312. &lt;p&gt;Below is the specification of the authorization API:&lt;/p&gt;
  313.  
  314. &lt;table&gt;
  315.    &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;URL&lt;/b&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;Configured on hosted.IM user administration form. Could be HTTPS (recommended) or HTTP&lt;/td&gt;&lt;/tr&gt;
  316.    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;GET&lt;/td&gt;&lt;/tr&gt;
  317.    &lt;tr&gt;&lt;td rowspan=&quot;4&quot;&gt;&lt;b&gt;Parameters&lt;/b&gt;&lt;/td&gt;&lt;td&gt;username&lt;/td&gt;&lt;td&gt;Username part of the user ID to be validated&lt;/td&gt;&lt;/tr&gt;
  318.    &lt;tr&gt;&lt;td&gt;password&lt;/td&gt;&lt;td&gt;Password sent by the user to be validated&lt;/td&gt;&lt;/tr&gt;
  319.    &lt;tr&gt;&lt;td&gt;domain&lt;/td&gt;&lt;td&gt;Domain part of the user ID to be validated&lt;/td&gt;&lt;/tr&gt;
  320.    &lt;tr&gt;&lt;td&gt;secret&lt;/td&gt;&lt;td&gt;Arbitrary string defined on hosted.IM user administration form&lt;/td&gt;&lt;/tr&gt;
  321.    &lt;tr&gt;&lt;td rowspan=&quot;3&quot;&gt;&lt;b&gt;Expected reply&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Code&lt;/td&gt;&lt;td&gt;200 OK&lt;/td&gt;&lt;/tr&gt;
  322.    &lt;tr&gt;&lt;td&gt;Content-type&lt;/td&gt;&lt;td&gt;application/json&lt;/td&gt;&lt;/tr&gt;
  323.    &lt;tr&gt;&lt;td&gt;Body&lt;/td&gt;&lt;td&gt;&lt;b&gt;true&lt;/b&gt; if authorized; otherwise &lt;b&gt;false&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
  324.    &lt;tr&gt;&lt;td rowspan=&quot;1&quot;&gt;&lt;b&gt;Error&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Code&lt;/td&gt;&lt;td&gt;Any HTTP code, according to the error type. It will deny user access.&lt;/td&gt;&lt;/tr&gt;
  325.    &lt;/tbody&gt;
  326. &lt;/table&gt;
  327.  
  328. &lt;br /&gt;
  329.  
  330. &lt;p&gt;This release also includes other improvements suggested by our users. It contains also bug fixes.&lt;/p&gt;
  331.  
  332. &lt;p&gt;As we continue improving daily our service, we will greatly welcome your feedback. There is already much more to come soon. Thank you!&lt;/p&gt;
  333.  
  334. &lt;p&gt;Links:&lt;/p&gt;
  335. &lt;ul&gt;
  336.    &lt;li&gt;&lt;a href=&quot;http://hosted.im&quot;&gt;http://hosted.im&lt;/a&gt;&lt;/li&gt;
  337.    &lt;li&gt;&lt;a href=&quot;http://www.process-one.net/en/forum/viewforum/26/&quot;&gt;hosted.IM support forum&lt;/a&gt;&lt;/li&gt;
  338.    &lt;li&gt;Twitter: &lt;a href=&quot;https://twitter.com/hosted_im&quot;&gt;@hosted_im&lt;/a&gt;&lt;/li&gt;
  339. &lt;/ul&gt;</description>
  340. <pubDate>Thu, 27 Oct 2011 15:18:11 +0000</pubDate>
  341. </item>
  342. <item>
  343. <title>Process One: ProcessOne webinar: XMPP-based Push Solutions</title>
  344. <guid>tag:process-one.net,2011:en/blogs/3.4812</guid>
  345. <link>http://www.process-one.net/en/blogs/article/processone_webinar_xmpp-based_push_solutions/</link>
  346. <description>&lt;p&gt;ProcessOne is holding a webinar about push solutions, based on XMPP and ejabberd.&lt;/p&gt;
  347. &lt;p&gt;XMPP is widely used as a push protocol for sending alerts and messages. It is at the heart of Apple Push Notification Server (APNS), Google Cloud to Device Messaging (C2DM), Nokia Notifications API and many other solutions like BBC radio notification system.&lt;/p&gt;
  348.  
  349. &lt;p&gt;&lt;img src=&quot;http://www.process-one.net/images/uploads/ProcessOne_Push.jpg&quot; alt=&quot;ProcessOne Push&quot; width=&quot;200&quot; height=&quot;200&quot; /&gt;&lt;/p&gt;
  350.  
  351. &lt;p&gt;This presentation explains what is the use of XMPP in those solutions and how XMPP can be use to do much more that chat systems.&lt;/p&gt;
  352.  
  353. &lt;p&gt;You will also learn how can ProcessOne help making realtime notifications, alerting and push a part of your business?&lt;/p&gt;
  354.  
  355. &lt;h2&gt;When?&lt;/h2&gt;
  356. &lt;p&gt;Wednesday, November 9, 2011&lt;br /&gt;&lt;/p&gt;
  357. &lt;p&gt;
  358. &lt;ul&gt;
  359. &lt;li&gt;06:00 PM - 07:00 PM - CET - Paris, Brussels, Berlin&lt;/li&gt;
  360. &lt;li&gt;12:00 AM - 01:00 PM - EDT - New York, Montreal&lt;/li&gt;
  361. &lt;li&gt;09:00 AM - 10:00 AM - PDT - San Francisco, Los Angeles&lt;/li&gt;
  362. &lt;/ul&gt;
  363. &lt;/p&gt;
  364.  
  365. &lt;h2&gt;Register!&lt;/h2&gt;
  366. &lt;p&gt;You need to &lt;a href=&quot;https://www2.gotomeeting.com/register/439179866&quot;&gt;register now&lt;/a&gt; in order to attend the webinar:&lt;br /&gt;
  367. &lt;ul&gt;&lt;li&gt;Registration URL: &lt;a href=&quot;https://www2.gotomeeting.com/register/439179866&quot;&gt;https://www2.gotomeeting.com/register/439179866&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;
  368.  
  369. &lt;p&gt;We hope to see you in great numbers!&lt;/p&gt;</description>
  370. <pubDate>Fri, 21 Oct 2011 14:13:20 +0000</pubDate>
  371. </item>
  372.  
  373. </channel>
  374. </rss>
  375.  
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda