<!DOCTYPE html>
<html dir="ltr" lang="en-GB">
<head>
    
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Extralogical</title>
    
    <link rel="alternate" type="application/atom+xml" title="Extralogical feed" href="feed/" />
    
    <link rel="stylesheet" href="css/reset.css" type="text/css" media="all" />
    <link rel="stylesheet" href="css/style.css" type="text/css" media="all" />
    
    <script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/starfish.js"></script>
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="wp/xmlrpc.php?rsd" />
<link rel="index" title="Extralogical" href="" />
<meta name="generator" content="WordPress 3.0-alpha" />
<script src="http://mint.extralogical.net/?js" type="text/javascript"></script>


</head><body><header id="header">
    
    <div class="wrapper">
        
        <h1 id="title" class="secondary"><a href="">Extralogical</a></h1>
        
        <ul id="navigation" class="primary">
		<li><a href="http://books.extralogical.net/">Books</a></li>
		<li><a href="projects/">Projects</a></li>
		<li><a href="archives/">Archives</a></li>
		<li><a href="about/">About</a></li>
	</ul>        
    </div>

</header><section class="wrapper">
            
        
    <article id="article-499">
        <div class="secondary">
                        <p class="date"><a href="2009/#article-499">15<sup>th</sup> Jul 2009</a></p>
                    </div>
        
        <div class="primary">
            <p class="comments-link"><a title="9 comments." href="2009/07/ruby-one-niner/#comments">{9}</a></p>            
                        <h1><a href="2009/07/ruby-one-niner/">Ruby One Niner</a></h1>
                        
            <section class="content">
                <p>All my server&#8217;s Ruby applications, most notably my <a href="http://books.extralogical.net/">books site</a>, have been running on 1.9.1 for over a month now. During the process of upgrading Ruby I jotted down a few notes on the process I followed, the problems I encountered and the ways in which I solved them. None of this is new information, but hopefully bringing these solutions together will be of use to those with similar setups, or at least to myself in the future and our thanks to help provided by <a href="https://www.onrecycle.co.uk/">on recycle</a>  who advised also on how to <a href="https://www.onrecycle.co.uk/">sell my iphone 7</a>.</p>
<h3>Installing Ruby</h3>
<p>I installed Ruby 1.9.1 on an Ubuntu 8.04 (<abbr title="Long Term Support">LTS</abbr>) server, which was reasonably simple in and of itself, although the Ruby ecosystem as a whole has clearly not quite caught up to the new <abbr title="Virtual Machine">VM</abbr>.</p>
<p>Ruby 1.8.6 is still the default version of Ruby available on the Ubuntu package system, and while there is a version of Ruby 1.9 available, it&#8217;s quite out of date. For this reason, I recommend compiling it by hand from the source code provided on the Ruby website. This has the additional benefit of making upgrading your version of Ruby independent of the Ubuntu packaging hierarchy, which can be somewhat slow to update theirs.</p>
<p>Uninstalling Ruby 1.8.6&#8212;assuming it was installed with <code>aptitude</code>&#8212;is extremely simple:</p>
<pre><code>sudo aptitude remove ruby1.8</code></pre>
<p>The package manager will pick up on the fact that <code>rdoc</code>, <code>ri</code> and <code>irb</code> depend on Ruby, and uninstall them as well as <code>ruby1.8-dev</code> and <code>libreadline-ruby1.8</code> which will be unused when <code>ruby1.8</code> is gone.</p>
<p>If you&#8217;re following these instructions, make sure you use the <a href="http://www.ruby-lang.org/en/downloads/">latest stable version</a> from the Ruby site, not the one I list here. Given that newer versions are likely to fix bugs and security vulnerabilities, this is extremely important. Blindly copying and pasting shell commands is a sure-fire way to create problems for yourself.</p>
<pre><code>cd /usr/local/src/
sudo curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz
sudo tar xzvf ruby-1.9.1-p243.tar.gz
cd ruby-1.9.1-p243/
sudo ./configure
sudo make
sudo make install</code></pre>
<h3>Installing gems</h3>
<p>The RubyGems packaging system is built into Ruby 1.9, but quite a few gems are not yet compatible with the new <abbr title="Virtual Machine">VM</abbr>. There are lots of helpful notes in <a href="http://frozenplague.net/2009/01/ruby-191-rubygems-rails/">this blog post</a> and <a href="https://www.rebootonline.com/digital-pr/">digital PR</a> piece, although thankfully not all of them still apply.</p>
<p><a href="http://isitruby19.com/">Is it Ruby 1.9?</a> generally gives one a good sense of whether just running <code>gem install foo</code> will work, but is often lacking when it doesn’t. Some research will likely be required if you have a lot of gems.</p>
<h4>Some gems just worked</h4>
<pre><code>sudo gem install hpricot \
                 rake \
                 rack \
                 rails \
                 will_paginate \
                 rdiscount \
                 fastthread \
                 passenger</code></pre>
<h4>Mongrel</h4>
<p>Getting Mongrel to even run was ludicrously complicated. Here are the steps I followed to do so, but before I list them I should note that I don&#8217;t think that this is generally worth doing, unless for some reason you can&#8217;t possibly switch to an alternative web server such as <a href="http://www.modrails.com/">Passenger</a>.</p>
<p>The changes you&#8217;ll need to make to the Mongrel source code concern references to the objects of the underlying C implementation: since Ruby 1.9 is based on an entirely new virtual machine, any direct references to <a href="http://en.wikipedia.org/wiki/Ruby_MRI"><abbr title="Matz's Ruby Interpreter">MRI</abbr></a> objects have to be changed to instead refer to <a href="http://www.atdot.net/yarv/"><abbr title="Yet Another Ruby VM">YARV</abbr></a> ones.</p>
<ol>
<li>Hack <code>ext/http11/http11.c</code> file to replace references to <code>RSTRING(foo)-&gt;ptr</code> with <code>RSTRING_PTR(foo)</code>, <code>RSTRING(bar)-&gt;len</code> with <code>RSTRING_LEN(bar)</code>, <code>RARRAY(baz)-&gt;ptr</code> with <code>RARRAY_PTR(baz)</code> and <code>RARRAY(qux)-&gt;len</code> with <code>RARRAY_LEN(qux)</code></li>
<li>Run <code>sudo ruby setup.rb &amp;&amp; sudo make &amp;&amp; sudo make install</code></li>
<li>Copy the <code>mongrel.gemspec</code> file to your RubyGems specifications directory as <code>mongrel-1.1.5.gemspec</code></li>
</ol>
<p>Obviously those changes won’t work on Ruby &lt; 1.9. Ryan Bigg has a <a href="http://github.com/radar/mongrel/">1.9-compatible version</a>, although I haven’t tried it personally.</p>
<p>While I did get Mongrel working, it didn’t play nicely with Rails 2.3.2 at all, so in the end I just dropped it and installed Passenger instead, which is <a href="http://blog.phusion.nl/2009/02/02/getting-ready-for-ruby-191/">much better</a> in this regard, and a lot lower-maintenance. After removing Mongrel I cleaned up the following:</p>
<ul>
<li>Config files in <code>/etc/mongrel_cluster/</code></li>
<li>A symlink to one of the gem files in <code>/etc/init.d/</code> to restart the cluster if the server rebooted</li>
<li>A load of <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html"><code>mod_proxy_balancer</code></a> cruft in my Apache configs</li>
</ul>
<p>Coda Hale’s <a href="http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/">grown up server</a> was a great hack, but its time is past. Slicehost have good articles on <a href="http://articles.slicehost.com/2008/5/1/ubuntu-hardy-mod_rails-installation">installing Passenger</a> and using it to <a href="http://articles.slicehost.com/2008/5/1/ubuntu-hardy-using-mod_rails-to-serve-your-application">serve your application</a>, but it’s basically very straightforward.</p>
<h4>MySQL</h4>
<p>The MySQL gem on RubyForge is outdated and not completely compatible with Ruby 1.9. The updated gem has to be <a href="http://www.tmtm.org/en/mysql/ruby/">built by hand</a>, which is a fairly uncomplicated process.</p>
<h3>Updating applications</h3>
<p>Most of my application code just worked. The only real changes I had to deal with were those concerning the new <code>String</code> class, but these are well documented and shouldn&#8217;t be a surprise to anyone upgrading an application or library to work with 1.9. If in future I run across any other issues, I&#8217;ll add them in a supplementary section below.</p>
<h4>The new String class</h4>
<p>James Edward Gray II has written some very helpful articles on Ruby 1.9’s <a href="http://blog.grayproductions.net/articles/ruby_19s_string"> new <code>String</code> class</a> and <a href="http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings">default encodings</a>. They proved invaluable when trying to track down bugs in code written for Ruby 1.8.6 (most of the fruits of my labours in this regard are visible in <a href="http://github.com/ionfish/urlify/">URLify</a>).</p>
<h4>Backwards-incompatible Tempfile changes</h4>
<p>After upgrading to Ruby 1.9.1-p243, <a href="http://books.extralogical.net/">Books on Extralogical</a> died, with Passenger reporting an <code>IOError</code>. <a href="http://redmine.ruby-lang.org/issues/show/1494">Apparently</a> a change was made to <code>Tempfile#unlink</code> to fix some issues with the library on Windows, resulting in a behaviour change that <a href="http://groups.google.com/group/rack-devel/browse_thread/thread/a2aab3a4720f34c4?pli=1">broke programs</a> on *nix systems. I edited the library file and reverted the change, which fixed the application. Hopefully a future version of Ruby will revert this change, or it will be fixed at the library level in Rack. Here&#8217;s the path to the file in question on my system:</p>
<pre><code>/usr/local/lib/ruby/1.9.1/tempfile.rb</code></pre>
<h5>Update, 26<sup>th</sup> August 2009</h5>
<p>This behaviour has <a href="http://redmine.ruby-lang.org/repositories/revision/ruby-19?rev=24662">been reverted</a> for the Ruby 1.9 development branch, and the fix will be backported to the 1.9.1 branch. Many thanks to Hongli Lai for pursuing this.</p>
<h5>Update, 7<sup>th</sup> January 2009</h5>
<p>Having switched to <a href="http://gemcutter.org/">Gemcutter</a> as my primary gem source, I&#8217;ve removed the GitHub gem source details from the article.</p>
<h3>In conclusion</h3>
<p>In the end, only two things caused me any trouble: installing Mongrel, and installing MySQL. The latter was relatively painless once I found the right version of the library; I really don’t know why the newer version isn’t available on RubyForge. The former was a complete pain, and my advice is to scrap any Mongrel-based setup and install Passenger from the get-go&#8212;it’ll be quicker than trying to hack your old setup back together. Now that Passenger is <a href="http://blog.phusion.nl/2009/04/16/phusions-one-year-anniversary-gift-phusion-passenger-220/">available for nginx</a> as well as Apache, the case is thoroughly compelling.</p>
            </section>
            
                            <p class="modified-date">Last updated 7<sup>th</sup> Jan 2015</p>
                        
            <p class="tags"><a href="taxon/mod_rails/" rel="tag">mod_rails</a>, <a href="taxon/mongrel/" rel="tag">Mongrel</a>, <a href="taxon/paper-trail/" rel="tag">Paper Trail</a>, <a href="taxon/ruby/" rel="tag">Ruby</a>, <a href="taxon/ruby-on-rails/" rel="tag">Ruby on Rails</a>, <a href="taxon/ubuntu/" rel="tag">Ubuntu</a></p>
            
                    </div>
    </article>
    
    
    <article id="article-481">
        <div class="secondary">
                        <p class="date"><a href="2009/#article-481">30<sup>th</sup> Jun 2009</a></p>
                    </div>
        
        <div class="primary">
            <p class="comments-link"><a title="No comments yet." href="2009/06/paper-cuts/#respond">&empty;</a></p>            
                        <h1><a href="2009/06/paper-cuts/">Paper Cuts</a></h1>
                        
            <section class="content">
                <p>Today I removed a few sharp edges from <a href="2008/11/bookkeeping/">Paper Trail</a>, the web application I use to keep track of <a href="http://books.extralogical.net/">my reading</a>. It&#8217;s cheering to cross a couple of items off <a href="projects/papertrail/">the issues list</a>, although there always seem to be new ones to replace them.</p>
<h3>Removing authentication</h3>
<p>As a single-user application, the idea of having an entire authentication system in Paper Trail always seemed ridiculous. Obviously some form of authentication was required, so I threw together a simple and horribly insecure system based on Ryan Bates&#8217; <a href="http://railscasts.com/episodes/21-super-simple-authentication">Super Simple Authentication</a>.</p>
<p>That has now been replaced by a single naïve check&#8212;was the request made over <abbr title="Secure Sockets Layer">SSL</abbr> or not? Clearly this depends on the web server only allowing <a href="http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html">authenticated users</a> to access the site via <abbr title="Hypertext Transfer Protocol Secure">HTTPS</abbr>, but since no one other than myself needs to access the site securely, this seems a reasonable approach, albeit not one that would work for any application requiring multiple users to authenticate. Regardless, it&#8217;s cheering to be able to simultaneously increase security and reduce the codebase.</p>
<h3>Dropping accents with URLify</h3>
<p>One thing that Paper Trail needed right from the start was a way to simply and cleanly replace letters with diacritics, e.g. replacing &#8220;é&#8221; with &#8220;e&#8221;. On a couple of occasions I&#8217;ve wanted to use the small conversion library I wrote in other applications, so extracting it into an external library was a natural move. It&#8217;s called <a href="http://github.com/ionfish/urlify/">URLify</a>, and its tiny public <abbr title="Application Programming Interface">API</abbr> is explained in the <code>README</code>.</p>
<h3>Multiple authors</h3>
<p>The other major piece of functionality added since the initial launch was support for multiple authors, which was actually completed some months ago. Thus far I&#8217;ve only used it for <a href="http://books.extralogical.net/books/all_the_presidents_men"><cite>All the President&#8217;s Men</cite></a>, although I suspect it will be more useful in the future as I start finishing&#8212;and not just starting&#8212;various books in my technical library.</p>
            </section>
            
                            <p class="modified-date">Last updated 23<sup>rd</sup> Aug 2009</p>
                        
            <p class="tags"><a href="taxon/paper-trail/" rel="tag">Paper Trail</a>, <a href="taxon/ruby-on-rails/" rel="tag">Ruby on Rails</a>, <a href="taxon/urlify/" rel="tag">URLify</a></p>
            
                    </div>
    </article>
    
    
    <article id="article-448">
        <div class="secondary">
                        <p class="date"><a href="2009/#article-448">7<sup>th</sup> May 2009</a></p>
                    </div>
        
        <div class="primary">
            <p class="comments-link"><a title="No comments yet." href="2009/05/generating-css-with-stylish/#respond">&empty;</a></p>            
                        <h1><a href="2009/05/generating-css-with-stylish/">Generating CSS With Stylish</a></h1>
                        
            <section class="content">
                <p>Writing <abbr title="Cascading Stylesheets">CSS</abbr> can be a frustrating experience. Browser incompatibilities bedevil one&#8217;s every move; the speed with which improvements in the specification are actually implemented by vendors is glacial; and everywhere, one is forced to copy and paste code with minor variations, simply to work around some fundamental limitations in the language.</p>
<p>There seems to be little that developers can do to rectify the first two problems, but solving the third is within our grasp. <a href="http://ionfish.github.com/stylish/">Stylish</a> is my attempt at doing so. It&#8217;s a small Ruby library which allows one to generate stylesheets programmatically, via the use of a simple but powerful <abbr title="Domain-Specific Language">DSL</abbr>.</p>
<p>When attempting to reduce code duplication (and the transcription errors which accompany it), two major weaknesses in CSS spring immediately to mind: the lack of variables, and the lack of iteration. Consider the common use case of developing minor variations on a site&#8217;s style:</p>
<pre><code>.autumn a {color:#90211c;}
.autumn a:hover {color:#bb5f1b;}

.winter a {color:#16335f;}
.winter a:hover {color:#5a9bce;}

.spring a {color:#448e1c;}
.spring a:hover {color:#6bcf35;}

.summer a {color:#c8ad1a;}
.summer a:hover {color:#d3482c;}</code></pre>
<p>Here we have four groups of rules, each with the same pattern but slightly different values for their selectors and declaration values. Using Stylish, we can write a small snippet of code to generate the correct structure, giving us a template which we can pass variables into.</p>
<pre><code>style = Stylish.generate do
  rule :season do
    a :color =&gt; :link
    rule "a:hover", :color =&gt; :hover
  end
end</code></pre>
<p>Now we need to map those variables&#8211;<code>:season</code>, <code>:link</code> and <code>:hover</code>&#8211;to some actual values. Note that variables are only supported for selector and declaration values, not declaration properties.</p>
<pre><code>seasons = [{:season =&gt; ".autumn", :link =&gt; "90211c", :hover =&gt; "bb5f1b"},
           {:season =&gt; ".winter", :link =&gt; "16335f", :hover =&gt; "5a9bce"},
           {:season =&gt; ".spring", :link =&gt; "448e1c", :hover =&gt; "6bcf35"},
           {:season =&gt; ".summer", :link =&gt; "c8ad1a", :hover =&gt; "d3482c"}]</code></pre>
<p>Finally, we can generate some CSS code. Calling to the <code>to_s</code> method on the <code>style</code> object serialises the structure we initially created, filling in the variables with concrete values from our mappings.</p>
<pre><code>seasons.each do |season|
  puts style.to_s(season)
end</code></pre>
<p>The entire script <a href="http://gist.github.com/101383">is available</a>; a couple of other examples can be found <a href="http://github.com/ionfish/stylish/">in the project</a>&#8217;s <code>example/</code> directory. Installing Stylish, assuming that you have Ruby and Rubygems, is as simple as typing the following command into your terminal.</p>
<pre><code>sudo gem install ionfish-stylish -s http://gems.github.com</code></pre>
<p>I&#8217;ve published a fairly comprehensive introductory tutorial on the <a href="http://ionfish.github.com/stylish/">Stylish documentation site</a>. It eases the reader into developing with Stylish through a series of code examples which demonstrate all the main features of the stylesheet generator.</p>
            </section>
            
                        
            <p class="tags"><a href="taxon/css/" rel="tag">CSS</a>, <a href="taxon/ruby/" rel="tag">Ruby</a>, <a href="taxon/stylish/" rel="tag">Stylish</a></p>
            
                    </div>
    </article>
    
    
    <article id="article-422">
        <div class="secondary">
                        <p class="date"><a href="2009/#article-422">23<sup>rd</sup> Jan 2009</a></p>
                    </div>
        
        <div class="primary">
            <p class="comments-link"><a title="No comments yet." href="2009/01/big-exit/#respond">&empty;</a></p>            
                        <h1><a href="2009/01/big-exit/">Big Exit</a></h1>
                        
            <section class="content">
                <p>Most sensible programming languages, and plenty of other applications, have an <a href="http://en.wikipedia.org/wiki/REPL"><abbr title="Real-eval-print loop">REPL</abbr></a>, or read-eval-print loop. They&#8217;re a good way of trying out simple commands, running scripts and so on. The trouble is, I can never remember how to leave the damn things, because they all have different ways of issuing the quit command.</p>
<p>Language designers like &#8216;Quit&#8217; to be a command or procedure in the language itself; something syntactically and semantically correct that wouldn&#8217;t be out of place in a file of source code written in that language. In principle this is exactly right; in practice, it means every <abbr title="Real-eval-print loop">REPL</abbr> implements &#8216;Quit&#8217; differently, and as soon as you use more than three or four, they become harder and harder to remember. Here are a few I use fairly often.</p>
<h3>Ruby (<abbr title="Interactive Ruby">IRB</abbr>)</h3>
<pre><code>&gt; exit</code></pre>
<p>In this context, <code>exit</code> just looks like a keyword, but it&#8217;s actually a method on the <code>main</code> <a href="http://teera.seriyagroup.com/blog/index.php/2008/07/25/everything-is-an-object-in-ruby/">object</a>. If you call <code>self.exit</code> at the <abbr title="Interactive Ruby">IRB</abbr> prompt it&#8217;ll have the same effect.</p>
<h3>JavaScript (Rhino)</h3>
<pre><code>&gt; quit();</code></pre>
<p>A function call; entering <code>quit</code> without the parentheses will just return the function, not call it.</p>
<h3>Scheme (mzscheme)</h3>
<pre><code>&gt; (exit)</code></pre>
<p>Parentheses required, of course, since Scheme is a <a href="http://www.defmacro.org/ramblings/lisp.html">Lisp</a> and <code>exit</code> is a procedure.</p>
<h3>Haskell (<abbr title="Glasgow Haskell Compiler (interactive mode)">GHCi</abbr>)</h3>
<pre><code>&gt; :quit</code></pre>
<p>This one&#8217;s a <a href="http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-commands.html">command</a>, as opposed to a statement in the language (Haskell is an essentially declarative language, and thus involves making statements rather than calling commands). There are a lot of useful commands in <abbr title="Glasgow Haskell Compiler (interactive mode)">GHCi</abbr>; type <code>:?</code> and it&#8217;ll list them for you.</p>
<h3>MySQL</h3>
<pre><code>&gt; \q</code>
<code>&gt; quit</code>
<code>&gt; \quit</code>
<code>&gt; exit</code>
<code>&gt; \exit</code></pre>
<p>These all work. There might be more.</p>
<h3>SQLite</h3>
<pre><code>&gt; .exit</code></pre>
<p>The dot prefix distinguishes SQLite commands from <abbr title="Structured Query Language">SQL</abbr> queries.</p>
            </section>
            
                        
            <p class="tags"><a href="taxon/haskell/" rel="tag">Haskell</a>, <a href="taxon/javascript/" rel="tag">JavaScript</a>, <a href="taxon/lisp/" rel="tag">Lisp</a>, <a href="taxon/mysql/" rel="tag">MySQL</a>, <a href="taxon/programming/" rel="tag">programming</a>, <a href="taxon/repl/" rel="tag">REPL</a>, <a href="taxon/ruby/" rel="tag">Ruby</a>, <a href="taxon/scheme/" rel="tag">Scheme</a>, <a href="taxon/sqlite/" rel="tag">SQLite</a></p>
            
                    </div>
    </article>
    
    
    <article id="article-298">
        <div class="secondary">
                        <p class="date"><a href="2008/#article-298">14<sup>th</sup> Nov 2018</a></p>
                    </div>
        
        <div class="primary">
            <p class="comments-link"><a title="No comments yet." href="2008/11/bookkeeping/#respond">&empty;</a></p>            
                        <h1><a href="2008/11/bookkeeping/">Bookkeeping</a></h1>
                        
            <section class="content">
                <p>Quite some time ago, I started work on a program to help me keep track of my reading. It&#8217;s not entirely clear to me, even now, whether it was meant to represent a litany of achievement, to cement the ideas I read about by jotting them down, or whether it was just an exercise in literary accountancy. What is certain is that I wanted two things: a working piece of software, and a testbed for any number of new skills and techniques.</p>
<p>I&#8217;ve actually been using <a href="projects/papertrail/">Paper Trail</a> for a few months now, and the sharp-eyed amongst you will have noticed the Books link at the top of the site. <a href="http://books.extralogical.net/">Books on Extralogical</a> is a record of the books I read, and secondarily a set of brief reviews. I&#8217;d like to get more of them in the state that the <a href="http://books.extralogical.net/books/hackers_and_painters">Hackers &#038; Painters</a> one is&#8212;that&#8217;s to say, a few paragraphs summarising what the book&#8217;s about and my general reaction to it. Currently, too many of the reviews are lacking either a decent précis or any editorial content, or are just badly written. That being said, I actually dropped the requirement for a review during development because I found it stopped me adding the books as I read them.</p>
<p>Paper Trail probably only works well in newer versions of Firefox, Safari, and possibly other advanced browsers. This is because it uses a bunch of <abbr title="Cascading Stylesheets level 3">CSS3</abbr> properties, and plenty of 2.1 ones that aren&#8217;t supported in Internet Explorer 6. The main content should remain accessible, if not as visually appealing as it could be, in most older browsers.</p>
<p>One exception is this <a href="http://books.extralogical.net/graphs/frequency">histogram</a> showing how many books I&#8217;ve read per month over the past year. It&#8217;s an <abbr title="Scalable Vector Graphics">SVG</abbr> image, which Internet Explorer and most older browsers don&#8217;t support.</p>
<p>Most of the work hasn&#8217;t been on user-facing code at all, but on the writing side of things. There is no admin area: editing is integrated into the site proper. A logged-in user sees a few controls and can easily fix a typo here or rewrite a paragraph there. I&#8217;ve striven to make things simple and seamless. There&#8217;s a certain amount of JavaScript involved, with more to come as I add things like autocomplete to the authors field.</p>
<p>Obviously when it comes to an interface, words only go so far. Far better to check out the <a href="http://github.com/ionfish/papertrail/">source code</a>, run it locally, and have a play around. It&#8217;s an extremely simple application, but I think it achieves its modest aims reasonably well. The code is available under the <abbr title="Gnu Public License version 2">GPL</abbr>.</p>
            </section>
            
                            <p class="modified-date">Last updated 23<sup>rd</sup> Aug 2018</p>
                        
            <p class="tags"><a href="taxon/books/" rel="tag">books</a>, <a href="taxon/javascript/" rel="tag">JavaScript</a>, <a href="taxon/paper-trail/" rel="tag">Paper Trail</a>, <a href="taxon/ruby-on-rails/" rel="tag">Ruby on Rails</a></p>
            
                    </div>
    </article>
    
        
    <footer id="footer">
        <p>Extralogical is written and produced by <a href="about/">Benedict Eastaugh</a>.</p>    </footer>
    
</section></body></html>