{"id":115,"date":"2008-04-09T19:23:07","date_gmt":"2008-04-10T00:23:07","guid":{"rendered":"http:\/\/dilettantes.code4lib.org\/?p=115"},"modified":"2008-04-09T19:23:07","modified_gmt":"2008-04-10T00:23:07","slug":"blindly-groping-towards-activeplatform","status":"publish","type":"post","link":"https:\/\/rossfsinger.me\/blog\/2008\/04\/blindly-groping-towards-activeplatform\/","title":{"rendered":"Blindly groping towards ActivePlatform"},"content":{"rendered":"<p>Something I&#8217;ve taken it upon myself to do since I joined Talis is make <a href=\"http:\/\/activerdf.org\/\" target=\"_blank\">ActiveRDF<\/a> a viable client to access the Platform.\u00c2\u00a0 While this is mostly selfishness on my part (I want to keep developing in Ruby and there&#8217;s basically no RDF support right now, plus this gives me a chance to learn about the RDF\/SPARQL-y aspects of the Platform), I also think that libraries like this can only help democratize the Platform.<\/p>\n<p>So far, it&#8217;s been pretty ugly.\u00c2\u00a0 I haven&#8217;t had much time to work on it, granted, but the time I&#8217;ve spent on it has made me think that there will be a lot of work to do.\u00c2\u00a0 Couple this with some of the things that make the Platform difficult to work with in Ruby anyway (read: Digest Authentication) and this might be a more uphill battle than I&#8217;ll <em>ever<\/em> have time for, but I figure it&#8217;s either this or go back to Python and I&#8217;m not quite ready to give up on Ruby yet.<\/p>\n<p>Currently, performance is abysmal with ActiveRDF against the Platform, so I&#8217;ll need to think of shortcuts to improve that (I&#8217;m not even considering write access presently).\u00c2\u00a0 Here&#8217;s some code (this is as much for my benefit, so I can remember what I&#8217;ve done) to work with Ian Davis&#8217; Quotations Book Example store:<\/p>\n<blockquote><p>require &#8216;time&#8217; # Otherwise ActiveRDF starts freaking out about DateTime<br \/>\nrequire &#8216;active_rdf&#8217;<\/p>\n<p>$activerdf_without_xsdtype = true<br \/>\n# less than ideal, but without it, ActiveRDF sends<br \/>\n# ^^&lt;http:\/\/www.w3.org\/2001\/XMLSchema#string&gt; with string literals even if you don&#8217;t want<br \/>\n# to send the datatype.\u00c2\u00a0 I haven&#8217;t actually tried it with other datatypes to see how this breaks<br \/>\n# down the road.<\/p>\n<p>ConnectionPool.set_data_source(:type =&gt; :sparql, :results =&gt; :sparql_xml, :engine=&gt;:joseki,\u00c2\u00a0 :url=&gt; &#8220;http:\/\/api.talis.com\/stores\/iand-dev2\/services\/sparql&#8221;)<\/p>\n<p>Namespace.register :foaf, &#8220;http:\/\/xmlns.com\/foaf\/0.1\/&#8221;<br \/>\nNamespace.register :dc, &#8220;http:\/\/purl.org\/dc\/elements\/1.1\/&#8221;<br \/>\nNamespace.register :quote, &#8220;http:\/\/purl.org\/vocab\/quotation\/schema&#8221;<\/p>\n<p>QUOTE::Quotations.find_by_dc::creator(&#8220;Loren, Sophia&#8221;).each do | quote |<\/p><\/blockquote>\n<blockquote><p># print the important stuff from each graph<\/p>\n<p># http:\/\/purl.org\/vocab\/quotation\/schema#quote has to be manually added as a predicate<br \/>\n# the &#8220;#&#8221; seems to cause problems<br \/>\nquote.add_predicate(:quote, QUOTE::quote)<br \/>\nputs quote.quote<br \/>\nputs quote.subject<br \/>\nputs quote.rights<br \/>\nputs quote.isPrimaryTopicOf<\/p><\/blockquote>\n<blockquote><p>end<\/p><\/blockquote>\n<p>If you actually try to execute this, you&#8217;ll see that it takes a long time to run (God help you if you try it on QUOTE::Quotations.find_by_dc::subject(&#8220;Age and Aging&#8221;)).\u00c2\u00a0 A really long time.<\/p>\n<p>If you set some environment vars before you go into irb:<\/p>\n<blockquote><p>$ export ACTIVE_RDF_LOG_LEVEL=0<br \/>\n$ export ACTIVE_RDF_LOG=.\/activerdf.log<\/p><\/blockquote>\n<p>then you can tail -f activerdf.log and see what exactly is happening.<\/p>\n<p>After ActiveRDF does it&#8217;s initial SPARQL query (<em>SELECT DISTINCT ?s WHERE { ?s &lt;http:\/\/purl.org\/dc\/elements\/1.1\/creator&gt; &#8220;Loren, Sophia&#8221; . }<\/em>), it&#8217;s doing two things for every request in the block:<\/p>\n<ol>\n<li>a SPARQL query for every predicate associated with the URI (<em>http:\/\/api.talis.com\/stores\/iand-dev2\/services\/sparql?query=SELECT+DISTINCT+%3Fp+WHERE+%7B+%3Chttp%3A%2F%2Fapi.talis.com%2Fstores%2Fiand-dev2%2Fitems%2F1187139384317%3E+%3Fp+%3Fo+.+%7D+<\/em>)<\/li>\n<li>a SPARQL query for the value of the attribute (predicate):\u00c2\u00a0 <em>http:\/\/api.talis.com\/stores\/iand-dev2\/services\/sparql?query=SELECT+DISTINCT+%3Fo+WHERE+%7B+%3Chttp%3A%2F%2Fapi.talis.com%2Fstores%2Fiand-dev2%2Fitems%2F1187139384317%3E+%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2Fcreator%3E+%3Fo+.+%7D<\/em><\/li>\n<\/ol>\n<p><em>for every predicate in the graph<\/em>.\u00c2\u00a0 You can imagine how crazily inefficient this is, since to get every value for a resource, you have to make a different HTTP request for each one.<\/p>\n<p>Obviously this would be a lot easier if it used DESCRIBE rather than SELECT, but without a real RDF library to parse the resulting graph, I&#8217;m not sure how ActiveRDF would deal with what the triple store returned.<\/p>\n<p>So, anyway, these are some of the hurdles in making ActiveRDF work with the Platform, but I&#8217;m not quite ready to throw in the towel, yet.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Something I&#8217;ve taken it upon myself to do since I joined Talis is make ActiveRDF a viable client to access the Platform.\u00c2\u00a0 While this is mostly selfishness on my part (I want to keep developing in Ruby and there&#8217;s basically no RDF support right now, plus this gives me a chance to learn about the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[50,3,49,39],"tags":[],"class_list":["post-115","post","type-post","status-publish","format-standard","hentry","category-activerdf","category-coding","category-platform","category-ruby"],"_links":{"self":[{"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/posts\/115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/comments?post=115"}],"version-history":[{"count":0,"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/posts\/115\/revisions"}],"wp:attachment":[{"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/media?parent=115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/categories?post=115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rossfsinger.me\/blog\/wp-json\/wp\/v2\/tags?post=115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}