Just A Summary : Category typo, everything about typo http://www.bofh.org.uk/articles/category/typo.rss en-us 40 Piers Cawley Practices Punditry The secret of comedy is... <p>... timing. You either have it or you don&#8217;t.</p> <p>Does this count as good timing?</p> <ol> <li>Finish up some improvements to the way Typo sweeps cached pages</li> <li>Announce Typo 5.0</li> <li>Go down with a horrible cough and cold that leaves you exhausted and incapable of hacking</li> <li>Discover that the &#8216;improvements&#8217; in Typo&#8217;s cache sweeping can, occasionally, cause it to wipe the entire Typo installation directory</li> <li>Stagger out of bed. Attempt to fix problem</li> <li>Release Typo 5.0.1</li> <li>Discover that the fix doesn&#8217;t work</li> <li>Bleargh!</li> <li>Let your co-maintainer deal with the fall out before releasing Typo 5.0.2 which <em>does</em> fix the cache sweeper</li> <li>We hope</li> <li>Recover enough to write a blog entry</li> </ol> <p>Okay folks, Typo 5.0.2 is out and it appears to be working. I&#8217;m running it here, and I&#8217;ve had no problems so far. I&#8217;ve <em>still</em> got the cold, but it&#8217;s nowhere near as horrible as it was (went to bed at 5pm on New Year&#8217;s Eve, woke up at 11am on New Years Day &#8211; first time I&#8217;ve missed the turning of the year in ages).</p> Tue, 08 Jan 2008 11:46:00 -0600 urn:uuid:66d6a51f-36f1-421f-9285-e0095cbe3fc0 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2008/01/08/the-secret-of-comedy-is#comments Typo http://www.bofh.org.uk/articles/2008/01/08/the-secret-of-comedy-is Typo 5 is out - and more on the future <p>Right, we&#8217;ve cut a Typo 5 gem and it&#8217;s on rubyforge and heading to various mirrors I hope. Frédéric&#8217;s writing the release notification which will be appearing on <a href="http://blog.typosphere.org/">Typosphere</a> Real Soon Now.</p> <p>It&#8217;s been a surprisingly tricky process &#8211; we&#8217;re now requiring Rails 2.0.2 because the workings of <code>view_paths</code> have changed in a way which means we can&#8217;t quite make themes with Rails 2.0 <em>and</em> 2.0.2 and working with the edge seems like the more sensible proposition. If you&#8217;re on the bleeding edge, you should find that you get the right Rails via svn:externals anyway.</p> <h3>Typo futures</h3> <p>Meanwhile, I&#8217;ve been playing with stet and I&#8217;ve come to the conclusion that, although there&#8217;s mileage to be had in a radically slimmed down approach to the way Typo works, I&#8217;m better off simply removing the misfeatures from Typo and building from there &#8211; there&#8217;s a surprising amount of <em>stuff</em> that needs to be done in a competent blogging engine that Typo gets right &#8211; starting again would be throwing the baby out with the bathwater I think.</p> <p>However, this does mean that if you&#8217;re following the Typo <span class="caps">SVN</span> trunk, you&#8217;ll be seeing a reduction in features in the short term. We&#8217;ll be copying the current trunk to a <code>5-0-stable</code> branch before we start with the featurectomies though, so if you&#8217;re just after bugfixes, you&#8217;ll be better off there.</p> <h4>Multiblogging</h4> <p>We&#8217;re aiming to have multiblogging in the next release, but we&#8217;re rethinking the <em>how</em> of it. Right now, the &#8216;Blog&#8217; object adds a bunch of complexity to code that would be much happier simply assuming that it has the database to itself. So we&#8217;re going to look at switching to a database per blog approach, that way our core code can pretty much forget about the complexities of multiblogging, and (at least initially) anyone who wants multiblogging can get there by monkeying with configuration files &#8211; of course, we intend to add a web based admin interface once things settle down and we know how things are going to work.</p> <h4>Caching</h4> <p>Caching is always a bugbear in any typo installation. Because we want to be installable on the widest possible range of hosts, we can&#8217;t rely on the presence of handy tools like &#8216;memcached&#8217;. Also, some of our users are operating under some fairly severe memory and process constraints, so it makes sense to have the webserve serve static files as much as possible. Meanwhile, tools like Evan Weaver&#8217;s <a href="http://blog.evanweaver.com/articles/2007/12/13/better-rails-caching/">Interlock</a> are pointing the way towards seriously effective fragment caching. I shall be looking into implementing something that conforms to the interlock interface, but which can use an arbitrary cache backing store for fragments <em>and</em> maintain a full page cache. It&#8217;ll be interesting to find out if this is doable&#8230;</p> <h4>Atom Publishing Protocol</h4> <p>ActionWebService is going to go away &#8211; it&#8217;s already in the <code>ousted</code> branch of the rails <span class="caps">SVN</span> repository, and including it in Typo to support the various different admin APIs is getting painful. So, we&#8217;re going to preempt it. We won&#8217;t be getting rid of the various <span class="caps">XMLRPC</span> APIs until the pain becomes too great, but we are going to be concentrating on implementing, and strongly favouring, the Atom Publishing Protocol.</p> <h4>Feeds for everything</h4> <p>In particular, we&#8217;ll be adding atom feeds for all sorts of administrative data as a means of enabling people to write external tools for, say, spam protection, comment moderation and notification tasks. Right now, there&#8217;s a great deal of computation happening on the server side every time someone, say, comments on a post &#8211; in the kind of resource limited environments some people are running Typo in, that&#8217;s too much work. Switching to a feed + <span class="caps">APP</span> approach should help enormously with resource utilization.</p> <h4>Speaking of resources&#8230;</h4> <p>Using the server to render article previews is&#8230; suboptimal. Expect to see a javascript based preview system akin to the one I use for comments here.</p> Sun, 30 Dec 2007 09:10:18 -0600 urn:uuid:72e74aa1-6450-438c-9757-81f8621b342c pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/12/30/typo-5-is-out-and-more-on-the-future#comments Ruby Typo http://www.bofh.org.uk/articles/2007/12/30/typo-5-is-out-and-more-on-the-future Rails 2.0 and the Future of Typo <p>So, if you&#8217;ve been watching the Typo tree, you&#8217;ll see there&#8217;s been a fair amount of activity on it since Rails 2.0 got released. There&#8217;s a new default theme replacing the rather creaky &#8216;azure&#8217;, and a fair amount of work on getting our code compatible with the current state of Rails. As we work on this, it becomes apparent that Typo&#8217;s code is getting horribly brittle. I have said before that there&#8217;s been several places where we&#8217;ve zigged before Rails zagged, and we&#8217;re paying the price for that. It doesn&#8217;t help that our test coverage is distinctly ropy either &#8211; and I&#8217;m probably guiltier than most for letting things get into that state.</p> <p>So, our goal is to get what we have cleaned up and working with Rails 2 before releasing Typo 5.0. Once that&#8217;s done, that line of code will go into maintenance mode &#8211; there are still plenty of bugs to fix and documentation to write, but I&#8217;m afraid that extending that base is becoming too much of a chore.</p> <p>Which is why I have a new path in my local svk repository, //stet. I&#8217;m using this for experimental development of a new, slimmed down blogging engine that will be, first and foremost, a capable Atom Publishing Protocol host. Things like spam processing will be removed from the core of the application, but we&#8217;ll provide a suite of webservice clients that will consume the &#8216;unmoderated feedback&#8217; webfeed and use <span class="caps">APP</span> to either approve or delete the feedback as appropriate.</p> <p>Theming (at least initially) will probably be confined to Javascript and <span class="caps">CSS</span> changes, and I&#8217;m even thinking of exposing the sidebars as Atom collections &#8211; certainly I expect that, in the first cut, sidebars will be static &#8211; if you want content that <em>looks</em> dynamic you&#8217;ll have to do it via javascript.</p> <p>My initial goal is to slim things down as far as I possibly can &#8211; I want to build a blogging engine that can cope with the tight memory constraints of shared hosting by off loading much of the heavy lifting to client boxes. After all, I have far more processing capability available to me on the laptop I&#8217;m typing this on than the slice of Site5&#8217;s hosting infrastructure that&#8217;s actually running the blog. By making things small and static, I also hope to wring good performance numbers out of the tool as well &#8211; expect aggressive page caching at the very least.</p> <p>Another important goal is easy migration of Typo databases. I expect to be writing models and controllers from the ground up, but converting the database should just be a matter of running a migration.</p> <h3>Experimental</h3> <p>Of course, stet&#8217;s currently <em>very</em> experimental &#8211; about the only thing that&#8217;s actually <em>written</em> so far are a couple of routing plugins which should help radically simplify our routes.rb (expect an article&#8217;s url to change from /articles/2007/12/16/rails-20-and-the-future-of-type to /article/2007/12/16/rails-20-and-the-future-of-typo, but with a redirect in place to cater for the old style urls). I may have grandish plans for the thing, but I could equally discover that I&#8217;m off up a blind alley, in which case you can expect me to return to the current typo codebase with a few more lessons learned.</p> <h4>ActiveResource?</h4> <p>I remain unconvinced by ActiveResource as a technology. I agree with the authors of <a href="http://www.amazon.co.uk/exec/obidos/ASIN/0596529260/justasummary-21">RESTful Webservices</a> &#8211; good webservices are joined up. They take full advantage of what could be described as the defining technology of the world wide web, the <span class="caps">URL</span> based hyperlink to knit resources together in a discoverable fashion. An ActiveResource based webservice may well be a good <span class="caps">HTTP</span> citizen, but it&#8217;s still not really &#8216;webby&#8217; enough for my taste. Which means the Atom Publishing Protocol will remain my friend for most of the things I hope to do with stet. It may be harder to write a good <span class="caps">APP</span> server, but I&#8217;m convinced that it&#8217;s a much better interface for clients, and you should always favour ease of use over ease of implementation. If nothing else, we&#8217;re aiming to have more users than developers. Many more.</p> Sun, 16 Dec 2007 10:35:00 -0600 urn:uuid:e685075e-992e-4813-b17d-3392fb9c1e91 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/12/16/rails-2-0-and-the-future-of-typo#comments Ruby Typo stet http://www.bofh.org.uk/articles/2007/12/16/rails-2-0-and-the-future-of-typo Typo on Rails 2 <p>Whee! Sat in my home directory is a version of typo that appears to work with Rails 2.0. I ended up giving up on the themer approach which proved to be very hard to get up and running transparently &#8211; things kept disappearing off around infinite loops, which is no fun at all, let me tell you.</p> <p>So, ended up cheating and ended up monkeying with <code>@@view_paths</code> directly, which is almost certainly against the rules, but has the cardinal virtue of <em>working</em>.</p> <p>I&#8217;m sanguine about it because the way themes worked on rails 1.2.x also involved fiddling with undocumented methods which aren&#8217;t there in edge rails.</p> <p>So, it now remains to walk around the thing, kick the tyres, write a few more tests and generally get myself to the point where I&#8217;m happy that it all works, and merge my local branch with the main line. I&#8217;m going to wait until 2.0.0 proper has been released, but now that I&#8217;ve done the work I expect to be merging it sharpish.</p> Fri, 05 Oct 2007 15:09:04 -0500 urn:uuid:9c882a49-4d7d-4ea1-a375-ea3ed954b875 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/10/05/typo-on-rails-2#comments Typo rails2 http://www.bofh.org.uk/articles/2007/10/05/typo-on-rails-2 My head hurts <p>During <span class="caps">DHH</span>&#8217;s keynote at RailsConf Europe it was apparent that there&#8217;s a great deal to like in edge rails, so I thought I&#8217;d have a crack at getting Typo up on it.</p> <p>Ow.</p> <p>I&#8217;d expected the pain points to be related to routing, but it seems that the rails routing system is approaching the level of the Excel calculation engine &#8211; nobody dares touch it for fear of breaking things, so typo&#8217;s custom routes seemed to work quite happily. There were a few things that have been deprecated, pluginized or moved out of the set of modules that&#8217;s automatically included when you do a <code>rake rails:freeze:edge</code>, but they were pretty easy to sort &#8211; the deprecation messages are a good deal more informative now than they were last time went deprecation squashing. There&#8217;s a surprising amount of stuff that&#8217;s been removed <em>without</em> any deprecation warnings though, which isn&#8217;t very sporting. <span class="caps">DHH</span> said there would likely be a 1.2.4 release (possibly a day before 2.0) with a bunch more deprecation warnings covering everything that&#8217;s <em>actually</em> going away, so if you&#8217;re thinking of moving a maturish app to Rails 2.0 it might make sense to wait for 1.2.4, install that, squash warnings, and move on up to 2.0.</p> <p>The real pain comes from themes. Typo&#8217;s themes rely on Rails internals working in a particular way, but they don&#8217;t work like that any more. In theory, the internals appear to be more theme friendly, related to allowing plugins to include views. The problem is, that it&#8217;s possible to change Typo&#8217;s theme without restarting the server, and the new themish internals don&#8217;t expect anything to change until the server&#8217;s restarted.</p> <p>So, I&#8217;ve been playing with plugins. The most promising approach appears to be that of the <a href="http://julik.textdriven.com/svn/tools/rails_plugins/themer/README">themer plugin</a>, which gets pretty close to doing what we need, and does it in a way that seems like it should work with both 1.2.3 and Edge Rails. It does appear to be making some radically different assumptions about the structure of the themes directory, but the basic framework is good and I should be able to make things work by making our current them object conform to Themer::Base&#8217;s interface and duck type my way to the sunny uplands of Edge Rails compatibility.</p> <p>Which will be nice.</p> <p>I like the themer approach a lot. Instead of monkeying about in the guts of rails, it monkeys about in <em>front</em> of Rails. It overrides <code>render</code> so that you can pass it a theme/lookup object. If it sees a lookup object, it uses that to rewrite the rest of the render arguments into a form that will render the right thing using the standard implementation of render. In a work project I&#8217;ve taken a similar approach to handling polymorphic routes for things like:</p> <div class="typocode"><pre><code class="typocode_default ">map.resources :pictures do |pics| pics.resources.comments end map.resources :users do |users| users.resources.comments end</code></pre></div> <p>I ended up with a <code>to_params</code> method defined on my <code>Comment</code> model, and stuck an extended <code>url_for</code> in front of the default Rails version, which looks something like:</p> <div class="typocode"><pre><code class="typocode_default ">def url_for_with_to_params(*arguments) if arguments[0].respond_to?(:to_params) with_options(arguments.shift.to_params) do |mapper| mapper.url_for_without_to_params(*arguments) end else url_for_without_to_params(*arguments) end end alias_method_chain :url_for, :to_params</code></pre></div> <p>Which is <em>so</em> much neater than the last time I attacked this particular problem (see the <a href="http://www.bofh.org.uk/articles/2007/01/25/initial-release-of-acts_as_resource">acts_as_resource</a> plugin).</p> <p>One of the nice things about Rails is that, although it&#8217;s opinionated and somewhat liberal with the syntactic vinegar for things the core team don&#8217;t think is the Right Way, they&#8217;re pretty good at leaving the door open for people like me who have other opinions. Both the themer plugin and my as yet unpluginized extension of <code>url_for</code> work by using existing capabilities in new ways and, because those <em>capabilities</em> are documented we can expect them to continue to work over multiple versions of Rails. Plugins that achieve similar effects by monkeying with Rails&#8217;s <em>internal</em> interfaces are hostages to fortune. Internal interfaces are free to change at any time, even between point releases, so a plugin can be left high and dry with surprising rapidity. Just ask the Rails Engines folk.</p> Sun, 23 Sep 2007 14:09:24 -0500 urn:uuid:1b4540f5-d2b4-4fac-b930-465f41608ca1 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/09/23/my-head-hurts#comments The Practice of Programming Ruby Typo http://www.bofh.org.uk/articles/2007/09/23/my-head-hurts Typo stuff <p>If you&#8217;ve been running on the <a href="http://www.typosphere.org/">Typo</a> edge recently, you&#8217;ll be all too painfully aware that there have been issues with the cache being flushed at the wrong times and not flushed at all at others. Which is not a happy state of affairs.</p> <p>However, I&#8217;ve recently got back to working on Typo and, after a few warmup refactorings and some missteps, I think caching is working properly now.</p> <p>There&#8217;s lots more work to do (there always is) but I reckon that you could do worse than bump your installation to r1513, which is what I&#8217;m running here.</p> Fri, 31 Aug 2007 03:07:04 -0500 urn:uuid:f0a2e6f7-1b6b-46f6-afbe-343e7cd272ee pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/31/typo-stuff#comments Typo http://www.bofh.org.uk/articles/2007/08/31/typo-stuff How I learned to stop worrying and love aggressive mockery <p>There&#8217;s something enormously liberating about writing an <a href="http://rspec.rubyforge.org/">RSpec</a> description that starts like:</p> <div class="typocode"><pre><code class="typocode_default ">describe ArticlesController, &quot;feeds:&quot; do before do @the_mock = mock('everything', :null_object =&gt; true) ActiveRecord::Base.stub!(:find).and_return(@the_mock) end it &quot;/articles.atom -&gt; atom feed&quot; do get :index, :format =&gt; 'atom' response.should render_template('_atom_feed') end ... end</code></pre></div> <p>The <code>:null_object</code> flag to rspec&#8217;s <code>mock</code> function is remarkably potent.The resulting mock will return itself from any method call that hasn&#8217;t got some other expectation set up. When I&#8217;m testing that my index methods render the appropriate views for the format, I don&#8217;t care that all the various variables have been set up correctly &#8211; I&#8217;ve already tested that in another description &#8211; I just want to get to the point where I&#8217;m about to render a template.</p> <p>What this does is decouple my tests. I can change the way that the index method fetches its stuff from the database and I&#8217;m only going to have to change the innards of the specs that test that.</p> <p>I tend to think of this as being analogous to the object oriented pattern of trying to write your methods at a single level of abstraction. Within a given spec, I should only be setting up expectations that are directly related to what I&#8217;m testing.</p> Wed, 06 Jun 2007 05:21:00 -0500 urn:uuid:2e16fe59-e574-4b39-9cd8-5f38bf91a873 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/06/06/how-i-learned-to-stop-worrying-and-love-aggressive-mockery#comments The Practice of Programming Ruby Typo http://www.bofh.org.uk/articles/2007/06/06/how-i-learned-to-stop-worrying-and-love-aggressive-mockery Dogfood time again <p>So, I just pushed the first step of what I&#8217;m thinking of as the Great Typo Controller Reorganization to the typo repository and updated things here. It&#8217;s always scary when I do that &#8211; local testing&#8217;s all very well, but running on a live site is a different matter.</p> <p>I&#8217;ll be talking about the changes in a later post, there&#8217;s a couple of things in the recent change that I&#8217;m rather pleased with, as well as a Rails plugin that I hope will be widely useful, but which I need to document.</p> Sat, 02 Jun 2007 03:08:00 -0500 urn:uuid:72c4d621-90ba-4158-b9a2-f8684d42b4a6 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/06/02/dogfood-time-again#comments Typo http://www.bofh.org.uk/articles/2007/06/02/dogfood-time-again What the? <p>Wow:</p> <div class="typocode"><pre><code class="typocode_default ">$ rake spec ... 156 examples, no failures $ ./script/spec spec ... 156 examples, 2 failures $ rake [unit tests, all pass] [functional tests, all pass] [specs...] 156 examples, 2 failures</code></pre></div> <p>For extra points, the 2 failures from running the plain <code>rake</code> are not the same as the failures from running <code>./script/spec spec</code>. And if I run <code>./script/spec spec</code> after a full <code>rake</code> run, I get a host of extra failures.</p> <p>I wonder what I&#8217;m doing to so comprehensively screw up test isolation.</p> <p>Ho hum.</p> Sun, 13 May 2007 03:42:00 -0500 urn:uuid:8c7bd369-f657-4534-839e-f9862d62b625 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/13/what-the#comments Ruby Typo testisolation http://www.bofh.org.uk/articles/2007/05/13/what-the Things which are fun <p>It&#8217;s definitely fun to commit a major rework of something that&#8217;s been bugging you to <span class="caps">SVN</span>. It&#8217;s slightly less fun to check it out in your production server and have it fall over until you remember you to retweak the environment.rb file.</p> <p>Anyhow, we&#8217;re now running on Typo 4.1.1+r1438. <a href="http://blog.typosphere.org/articles/2007/05/08/its-here-its-new-its-improved-its">Typo 4.1.1</a> got released last night and, pretty much as soon as it had cleared the gates I checked in a major rework of the Article and Feedback state mechanisms.</p> <h3>What state mechanisms?</h3> <p>When you&#8217;re modelling blog posts, and comments, it&#8217;s very easy to think of them in terms of simple status flags. An article is published, or its a draft, so we have a <code>#published</code> boolean and we&#8217;re done.</p> <p>Except, what about an article that you want to publish at a specific time? And how do we work out when to send notifications and trackback pings? Should you send the pings again when an article is first published then withdrawn, then published again?</p> <p>It&#8217;s complicated, and you can end up with a rats nest of complex conditional code.</p> <p>So, you work out that an article can be in one of several states. We went with <code>:new</code>, <code>:draft</code>, <code>:just_published</code>, <code>:published</code>, <code>:publication_pending</code>, <code>:just_withdrawn</code> and <code>:withdrawn</code>, and we used the State Pattern to handle this. All our tangled conditionals were replaced with simple delegations to the state object. There&#8217;s still <em>some</em> conditional code, but there&#8217;s a great deal less of it now.</p> <p>Until recently, we implemented the states using Rails&#8217;s <code>composed_of</code> helper, but it&#8217;s not really suited to the task &#8211; you know your code isn&#8217;t happy when you find yourself calling a class <code>ContentState::Factory</code> and overriding its <code>new</code> method. It was also really hard to divine the workings of the state machine.</p> <p>So, during a discussion of <a href="http://giantrobots.thoughtbot.com/2007/5/1/coding-without-ifs">Coding without ifs</a> I found myself sketching a way of setting up a state field declaratively and thought to myself &#8220;Hey, I could implement that for Typo and make things a good deal clearer&#8230;&#8221;</p> <p>So I did.</p> <p>Now, if you look at the top of <code>article.rb</code>, you&#8217;ll find:</p> <div class="typocode"><pre><code class="typocode_default "> has_state(:state, :valid_states =&gt; [:new, :draft, :publication_pending, :just_published, :published, :just_withdrawn, :withdrawn], :initial_state =&gt; :new, :handles =&gt; [:withdraw, :post_trigger, :after_save, :send_pings, :send_notifications, :published_at=, :published=, :just_published?]) include States</code></pre></div> <p>And it sets up the delegations (as well as a set of <code>#new?</code>, <code>#draft?</code>, ... predicates based on the names of the valid states) for you. I pulled the States module out into a separate <code>article/states.rb</code> file, but given a simple set of states there&#8217;s no reason not to declare them inline.</p> <p>I&#8217;m really pleased with it. I&#8217;ll probably do a bit more work on the interface (I want it to be more language like), add a <code>has_strategy</code> declaration (which I intend to use for our feedback spam checking system) and then extract a plugin from it. If you&#8217;re interested in doing something similar in your own code right now, the thing you need to pinch is <code>lib/stateful.rb</code> in the Typo distribution, and the only documentation is the source. Check <code>app/models/feedback/states.rb</code> and <code>app/models/article/states.rb</code> for examples of states written to this interface.</p> Tue, 08 May 2007 02:12:00 -0500 urn:uuid:8ff4e40a-a647-4e3e-ba5c-fa989c904254 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/08/things-which-are-fun#comments Ruby Typo http://www.bofh.org.uk/articles/2007/05/08/things-which-are-fun Other things which aren't fun <p>Last year, you would have been forgiven for thinking that Typo was pretty much dead in the water as an ongoing project. <a href="http://www.typosphere.org/">Typosphere</a> was a placeholder, changes were few and far between, the app was a bloated monster. So, people switched, in droves, to <a href="http://www.mephistoblog.com/">Mephisto</a> the new, (and excellent) kid on the block. Heck, even <a href="http://blog.leetsoft.com/">Tobi</a>, the original author of Typo, has switched.</p> <p>Mephisto&#8217;s a great piece of software, and I&#8217;m as sure as I can be (without taking a closer look) that its underpinning code is cleaner than typo&#8217;s. When you&#8217;re developing on a rapidly moving platform like Ruby on Rails, there could be said to be a second mover advantage &#8211; the later you start, the more likely Rails is to already do what you want, and the less likely you are to zag where Rails later zigs.</p> <p>However, <a href="http://www.technoweenie.com/">Rick</a> and <a href="http://alternateidea.com/">Justin</a> have other projects and demands on their time, and once something is Good Enough, it&#8217;s hard to summon up the motivation to make it better until you find something that <em>you</em> want your application to do.</p> <p>So now, as Typo comes out of hibernation, it seems that Rick and Justin have been getting it in the neck because their project is &#8216;<a href="http://www.mephistoblog.com/2007/3/22/is-mephisto-dead">stalled</a>&#8217;. Okay, so I admit, I did smile ruefully to myself when I read that.</p> <p>Then I read the comments. Wow. Some people have some serious entitlement issues.</p> <p>It&#8217;s been said before, it&#8217;ll be said again I&#8217;m sure: if you don&#8217;t like something about an open source project, &#8220;Patches welcome!&#8221;. If your patches are repeatedly rejected: it&#8217;s open source, fork off. If a project is moribund: offer to help.</p> <p>Complaints just put people&#8217;s backs up.</p> <p>I think it&#8217;s great that there&#8217;s choices available if you want a blog built Rails. Different perspectives on a problem space are important &#8211; if nothing else, everyone gets to steal from each other, everyone&#8217;s apps get better and everybody wins.</p> Mon, 07 May 2007 14:29:00 -0500 urn:uuid:a9679735-8b8f-4d7e-ad37-201d643b178e pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/07/other-things-which-arent-fun#comments Ruby Typo mephistoblog typo entitlement http://www.bofh.org.uk/articles/2007/05/07/other-things-which-arent-fun Things which aren't fun <p>Let&#8217;s say you&#8217;re running tests against your rails application and a test fails.</p> <p>&#8220;Hmm&#8230;&#8221; you think, &#8220;I wonder what could be causing that, let&#8217;s run that test file by itself.&#8221;</p> <p>The test passes.</p> <p>&#8220;Okay&#8230; I wonder if it&#8217;s the rake test loader, let&#8217;s run that test file using that.&#8221;</p> <p>The test passes</p> <p>&#8220;Right, it&#8217;s only the third test file on the list that&#8217;s failing, let&#8217;s try running just the first 3 test files.&#8221;</p> <p>The test fails.</p> <p>&#8220;Okay, so it&#8217;s one of the first two test files that&#8217;s causing the problem. Let&#8217;s remove one and see what happens.&#8221;</p> <p>The test passes.</p> <p>&#8220;Right, because I&#8217;m paranoid, let&#8217;s try running it with the other test file instead. It should fail.&#8221;</p> <p>The test passes.</p> <p>&#8220;Hmm&#8230; the failure appears to be fixture related, let&#8217;s try turning of <code>use_transactional_fixtures</code> in <code>test_helper.rb</code> and running the failing set of tests again.&#8221;</p> <p>The test passes.</p> <h3>Houston, we have a problem</h3> <p>Part of our problem is that Typo is so huge and old, and its test suite is somewhat spotty. Something we&#8217;re doing in the workings of a couple of our controllers is confusing transactional fixtures and that can&#8217;t be good. I suppose my first step is to get all the tests that are still failing with transactional fixtures turned off passing and see if that solves my transactional problem, but I can&#8217;t pretend it&#8217;s a fun option.</p> Mon, 07 May 2007 09:13:00 -0500 urn:uuid:41dacd60-094c-4157-bd28-13967abbc5e4 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/05/07/things-which-arent-fun#comments Ruby Typo http://www.bofh.org.uk/articles/2007/05/07/things-which-arent-fun Cunning Typo Sidebar Tricks <p>If you&#8217;re reading this on the website rather than through a feedreader and you look to the left you&#8217;ll see either a bunch of links to cited books or an Amazon &#8216;self optimizing links&#8217; banner (though, if it keeps &#8216;optimizing&#8217; like it has being I&#8217;ll be changing it to something else). This is implemented using a mildly hacked version of the standard typo <code>amazon_sidebar</code> plugin.</p> <p>&#8220;But,&#8221; I hear you say, &#8220;The sidebar&#8217;s over on the right, and Typo can only support one sidebar.&#8221;</p> <p>And you&#8217;re right, Typo&#8217;s admin interface can only handle configuring one sidebar, and I&#8217;m not entirely sure how to make it work with too &#8211; hopefully our new maintainer and usability advocate, <a href="http://fredericdevillamil.com/">Fr&eacute;d&eacute;ric de Villamil</a> has some ideas along those lines. So, how does it work.</p> <p>Let&#8217;s take a look at a fragment of my <code>layouts/default.rhtml</code> file shall we?</p> <div class="typocode"><pre><code class="typocode_default ">&lt;div id=&quot;sidebar_lhs&quot;&gt; &lt;%= render_sidebars \ AmazonSidebar.new \ :title =&gt; 'Citations', :associate_id =&gt; 'justasummary-20', :maxlinks =&gt; 10) %&gt; &lt;/div&gt;</code></pre></div> <p>The thing about Sidebar objects is that there&#8217;s no real need to store them in the database. It&#8217;s done as a convenience so you can manage them through the admin interface, but if you want to use a sidebar widget anywhere in your layout there&#8217;s nothing stopping you.</p> <p>Actually, that&#8217;s not quite true, before revision <a href="http://trac.typosphere.org/changeset/1407">#1407</a>, the <code>render_sidebars</code> helper couldn&#8217;t take an argument, so you had to jump through a bunch more hoops, but (as you&#8217;ll see if you follow the link), the code change is trivial, if you need the functionality but don&#8217;t want to move to an <span class="caps">SVN</span> version of typo you can just change that one helper. The change should work in any Typo newer than about 8 months old, and the underlying idea should work with much older version too, you&#8217;ll just have to think a bit harder to apply the patch.</p> Sat, 14 Apr 2007 03:36:16 -0500 urn:uuid:0a3cb700-bc5e-4821-9044-fbde87e8ef7e pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/04/14/cunning-typo-sidebar-tricks#comments Typo http://www.bofh.org.uk/trackbacks?article_id=cunning-typo-sidebar-tricks&day=14&month=04&year=2007 http://www.bofh.org.uk/articles/2007/04/14/cunning-typo-sidebar-tricks Typo Brain Dump <p>In case anyone&#8217;s interested, I&#8217;ve written a list of some of the things I&#8217;m currently mulling doing with Typo below the fold.</p> <h3>Sorting out routes</h3> <p>I&#8217;ve mentioned this before I&#8217;m sure, but I&#8217;m not entirely happy with the current state of Rails&#8217;s routing. I&#8217;m not talking about the actual underlying code (which is scary enough), more about what it can do. The problem is that you have to know the specifics of what makes up a route in order to generate one. And you have to know it everywhere you use the route. You can make good enough guesses when you&#8217;ve got &#8216;simple&#8217; routes &#8211; I wrote <code>acts_as_resource</code> to do just that, but it doesn&#8217;t work for Typo&#8217;s routes.</p> <p>Consider the two sorts of things Typo can provide a feed of: articles and comments. In a perfect world we could use pretty much the same builder templates for everything and generate the routes simply by calling <code>url_for(@thing)</code>, which would generate a link to <code>/articles/2007/04/13/typo-brain-dump</code>, or <code>/articles/2007/04/13/typo-brain-dump#comment-212</code> as appropriate. It&#8217;s at its ugliest in the comment case. There you are, innocently generating a link to a comment and you&#8217;re required to know that its <span class="caps">URL</span> is generated from the broken down publication date of the original article and its &#8216;permalink&#8217;, and you have to remember what the parameters are called. Suddenly you&#8217;re writing code like:</p> <div class="typocode"><pre><code class="typocode_default "> article = comment.article url_for \ :year =&gt; article.year, :month =&gt; article.month, :article.day =&gt; article.day, :title =&gt; article.permalink, :anchor =&gt; &quot;comment-#{self.id}&quot;</code></pre></div> <p>Even when you hide that behind a helper method it&#8217;s all kinds of ugly. We&#8217;ve cheated slightly and taken the view that, since we&#8217;re modelling <em>webpages</em> here, it makes sense that they would know their URLs<sup><a href="#fn1">1</a></sup>, so you find a comment&#8217;s <span class="caps">URL</span> by doing <code>a_comment.permalink_url</code>, which looks like:</p> <div class="typocode"><pre><code class="typocode_default "> def permalink_url(anchor=:ignored, only_path=true) self.article.permalink_url(&quot;comment-#{id}&quot;) end</code></pre></div> <p>But that tends to make people who still think that objects are data structures throw a bit of a wobbly.</p> <p>My current thinking on how to reduce the pain here is to rejig Rails routing to allow it to multilevel keys, so the basic article <span class="caps">URL</span> would be specified as:</p> <div class="typocode"><pre><code class="typocode_default "> /articles/:article[year]/:article[month]/:article[day]/:article[permalink]</code></pre></div> <p>In a perfect world, &#8216;articles&#8217; would be inflected, so an article&#8217;s <span class="caps">URL</span> would be <code>/article/2007/04/13/typo-brain-dump</code>, but the <span class="caps">URL</span> for all the articles posted in April 2007 would be <code>/articles/2007/04/</code>, but I&#8217;ll worry about that. For now I can set up specific routes and have done.</p> <p>I&#8217;ve started work on this, but it&#8217;s proving tricky… Ho hum, no reason to stop striving I suppose.</p> <h3>Atom Publishing Protocol</h3> <p>The Atom Publishing Protocol is just lovely. Typo should support it. That is all.</p> <h3>Canvas based rendering</h3> <p>I really don&#8217;t like <span class="caps">RHTML</span> templates. Or <span class="caps">HAML</span> ones. Builder&#8217;s okay, but it seems to me that Seaside has this dead right. We should be passing a canvas/builder object to a model&#8217;s <code>#render_on</code> method and then calling <code>#to_html</code>, <code>#to_xml</code>, <code>#to_json</code> or whatever on the object we passed in. There&#8217;s probably a whole series of posts around this idea, starting with how using such a mechanism would allow for some seriously potent filtering and other capabilities and working up to how we&#8217;d make theming work (I think it&#8217;s possible to support existing themes with some fancy footwork, but I need to experiment).</p> <p>A question for the lazy web: Is anyone already doing canvas based rendering in Ruby?</p> <h3>Cruft</h3> <p>There&#8217;s too much <em>code</em> in Typo. It could stand to receive some serious pruning and refactoring. The problem with this is confidence in the test suite which manages to be large, fairly brittle and inadequate all at once.</p> <p>And it&#8217;s at least as much my fault as it is anyone else&#8217;s. I need to go through the test and get some kind of handle on where it needs to be extended to cover what Typo actually does. And then I need to extend it. And fix the test names. And empty all those horrible <span class="caps">YAML</span> fixture files. And&#8230;</p> <p id="fn1"><sup>1</sup> It&#8217;s not quite that simple (hah!). Articles and Comments don&#8217;t know their URLs, the Blog object is the repository of that knowledge, but they do know which of their attributes are important for building a <span class="caps">URL</span>. <code>Comment#permalink_url</code> delegates to <code>Article#permalink_url</code>, which in turn calls <code>Blog#url_for</code>, which mocks up an ActionController and delegates to that.</p> Fri, 13 Apr 2007 12:51:00 -0500 urn:uuid:71d7e8fc-921d-4463-8793-3f58ef1bb64d pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/04/13/typo-brain-dump#comments Typo http://www.bofh.org.uk/articles/2007/04/13/typo-brain-dump Cover me; I'm going in! <p>Mmm&#8230; Rails routes, don&#8217;t you love them?</p> <p>Well, not unreservedly, no.</p> <p>Here&#8217;s my current problem: Typo articles have a permalink that looks like <code>/articles/:year/:month/:mday/:permalink</code>, so the permalink for this article is <code>/articles/2007/03/15/cover-me-im-going-in</code> and when someone visits it, the controller gets a params hash which contains keys along the lines of:</p> <pre><code>{ :year =&gt; '2007', :month =&gt; '03', :mday =&gt; '15', :permalink =&gt; 'cover-me-im-going-in', # the session, controller, etc }</code></pre> <p>Which is okay as far as it goes<sup><a href="#fn1">1</a></sup>, but it&#8217;s a complete pain when it comes to generating the url. I have to do:</p> <pre><code>url_for :year =&gt; @article.year, :month =&gt; @article.month, :mday =&gt; @article.mday, :permalink =&gt; @article.permalink</code></pre> <p>Every value in that hash is dependent on a single object, every key is the same as the method used to find its associated value. I want to be able to write a route that looks like this:</p> <pre><code>map.article_url \ '/articles/:article[year]/:article[month]/:article[mday]/:article[permalink]', :controller =&gt; 'articles', :action =&gt; 'show'</code></pre> <pre><code>article_url @article # generates the route</code></pre> <p>That&#8217;ll do for starters; I&#8217;ll worry about making it Resourceful once I&#8217;ve got the basic recognizer and generator working.</p> <p>So, that&#8217;s what I shall be working on within <code>acts_as_resource</code> for the next while. Once I&#8217;ve got it working, I&#8217;ll start using it within Typo and we can get rid of the various model methods we ended up adding to cope with generating our URLs.</p> <h3>Why bother?</h3> <p>The thing to remember is that, while routes like <code>/:resources/:id</code> are okay when you&#8217;re prototyping, they&#8217;re problematic for production. Opacity is not a virtue. Exposing internal database keys in the <span class="caps">URL</span> is a positive vice.</p> <p>Meanwhile <code>/articles/2007/03/15</code>, <code>/articles/2007/03</code> and <code>/articles/2007</code> all have obvious meanings and typo supplies the obvious index pages when you go to look at them.</p> <p id="fn1"><sup>1</sup> However, it would be better if it were actually more like: <code>{:article =&gt; {:year =&gt; '2007', ...}, :controller =&gt; ...}</code> because then I can find the article by a simple <code>Article.find(:first, :conditions =&gt; params[:article])</code> and let <code>sanitize_sql</code> do all the work for me.</p> Thu, 15 Mar 2007 14:06:00 -0500 urn:uuid:2d2d02f7-8ccd-4d32-af55-461b6943cde0 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/03/15/cover-me-im-going-in#comments The Practice of Programming Ruby Typo http://www.bofh.org.uk/articles/2007/03/15/cover-me-im-going-in Getting the Rspec religion <p>I&#8217;ve been eyeing the <a href="http://rspec.rubyforge.org/index.html">rspec</a> and rspec on rails packages and thinking I should give them a go.</p> <p>To my eye at least, something like:</p> <div class="typocode"><pre><code class="typocode_default ">context 'Given a published article' do fixtures :contents setup { @article = contents(:published_article) } specify 'changing content invalidates the cache' do @article.body = 'new body' @article.invalidates_cache?.should_be true end end context 'Given an unpublished article' do fixtures :contents setup { @article = contents(:unpublished_article) } specify 'changing content keeps the cache' do @article.body = 'new body' @article.invalidates_cache?.should_be false end end</code></pre></div> <p>reads far more fluently than the equivalent Test::Unit based tests:</p> <div class="typocode"><pre><code class="typocode_default ">class CacheSupportTest &lt; Test::Unit::TestCase fixtures :contents def test_changing_published_article_invalidates_the_cache art = contents(:published_article) art.body = 'new body' assert art.invalidates_cache? end def test_changing_unpublished_article_keeps_the_cache art = contents(:unpublished_article) art.body = 'new body' assert ! art.invalidates_cache? end end</code></pre></div> <p>So, I installed everything and started to work on a new class in Typo using rspec. Rather annoyingly, this seemed to break the current test suite, so instead of working on my new model class, I set to porting the existing suite.</p> <p>And, on about my third test suite, I found what I think is a bug in the suite. I&#8217;m not <em>sure</em> it&#8217;s a bug, because, the way the test is written (by me, I admit it), masks the intent quite dramatically. I&#8217;m also finding that the freedom to name specifications and contexts in English rather than <code>method_names_that_go_on_for_ever</code> is forcing me to come up with much more useful descriptions of what I&#8217;m testing. I find myself working on making the spec runner output read reasonably well as English, and doing that casts light on what is and isn&#8217;t being tested.</p> <p>I&#8217;ve known for a while that Typo&#8217;s test suite is, um, spotty, but the porting process is really helping me get familiar with what&#8217;s being tested. I&#8217;m half tempted to start adding extra specs as I go, and if I could work out how to keep the existing tests working while I did it, I would, but my priority for now is to get to the point where I can check the specs and be confident that the new specs are no worse than the old tests.</p> <p>Because I&#8217;m much more confident that I know what the specs are <em>doing</em>, I&#8217;m also confident that it won&#8217;t be hard to revisit them to help specify typo&#8217;s behaviour better. I&#8217;ll just have to give myself the discipline of beginning each coding session with half an hour of fleshing out the specifications before I get back to adding behaviour.</p> Sun, 26 Nov 2006 02:52:00 -0600 urn:uuid:30163f70-ce19-4a05-8e66-e6532c674385 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/11/26/getting-the-rspec-religion#comments The Practice of Programming Ruby Typo rspec http://www.bofh.org.uk/articles/2006/11/26/getting-the-rspec-religion A sketch of declarative ActiveRecord Migrations <p>Writing migrations can get pretty tedious when you&#8217;re being scrupulous about writing both the up and the down side of the migration. Okay, so the <a href="http://macromates.com/">Textmate</a> ninjas amongst you can use scarily clever snippets to populate the <code>down</code> migration while you write the <code>up</code> method, but I can&#8217;t be the only Mac user who still prefers Emacs. And not everyone gets to run on Macs either.</p> <p>So, inspired by something Jamis Buck wrote about <a href="http://weblog.jamisbuck.org/2006/11/13/designing-a-dsl">designing a <span class="caps">DSL</span></a>, I&#8217;ve been sketching out a <span class="caps">DSL</span> for describing the easy parts of a migration in declarative style. None of this is implemented yet, but I&#8217;m pretty sure that it&#8217;s relatively simple to implement for a decent Ruby metaprogrammer. I&#8217;m brain dumping it here so I can come back to it later, or, you never know, someone might have implemented it by the time I revisit&#8230;</p> <h3>The sketch</h3> <div class="typocode"><pre><code class="typocode_default ">class AdjustContentTable &lt; ActiveRecord::Migration class Content &lt; ActiveRecord::Base include ActiveRecord::Migration::Delta delta do +(:extended, :text) -(:excerpt, :text) +index :text_filter_id end end end callbacks_for(:up) do before_any_changes Content.before_changes { ... } Content.before_additions {...} Content.after_additions {...} Content.before_removals {...} Content.after_removals {...} Content.after_changes {...} after_any_changes end callbacks_for(:down) do ... end end</code></pre></div> <h3>Implementation Pointers</h3> <p>By making <code>delta</code> do its work in a block, it&#8217;s possible to <code>instance_eval</code> the block using a <code>Delta</code> object that has appropriate implementations of <code>+</code> and <code>-</code>.</p> Then <code>callbacks_for[:up]</code> puts its block into, say <code>@callbacks[:up]</code> and the block is yielded to to set up the callbacks by the default implementation of <code>up</code>. The default <code>up</code> probably looks something like: <div class="typocode"><pre><code class="typocode_default "> def self.up @callbacks[:up].call apply_all_deltas end</code></pre></div> Of course the fun bit is the implementation of <code>apply_all_deltas</code> &#8211; the per class <code>apply_delta</code> is reasonably simple: <div class="typocode"><pre><code class="typocode_default "> def self.apply_delta(direction) callback(:before_changes) apply_additions(direction) apply_removals(direction) callback(:after_changes) end def self.apply_additions(direction) if has_additions?(direction) callback(:before_additions) eval additions_for(direction).to_ruby callback(:after_additions) end end ...</code></pre></div> <p>Thinking about it, <code>apply_all_deltas</code> is going to take a certain amount of grovelling about in the namespace to work out what classes need to have their deltas applied, but even with just per class delta declarations, this should be a useful thing to implement.</p> <h3>Braindump ends</h3> <p>Sorry this doesn&#8217;t come with a handy dandy Rails plugin with it all implemented; your contributions in this area would be very gratefully received.</p> Fri, 24 Nov 2006 06:18:00 -0600 urn:uuid:e2dc28b9-7fac-4696-b12a-d1c3e72c21b4 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/11/24/a-sketch-of-declarative-activerecord-migrations#comments Ruby Typo typo rubyonrails dsl lazyweb http://www.bofh.org.uk/articles/2006/11/24/a-sketch-of-declarative-activerecord-migrations Typo on Rails 1.2 <p>Typo users with longish memories will recall the absolute disaster we had when Rails 1.1 shipped and Typo wasn&#8217;t even remotely compatible with it. Even edge Typo didn&#8217;t work with 1.1. Chaos and confusion, strong words from <span class="caps">DHH</span>, all manner of unfun things.</p> <p>So, this time, we&#8217;re not going to let it happen. We hope.</p> <p>For starters, the current Typo release, 4.0.3 is locked to Rails 1.1.6 &#8211; if you install it from the gem it will insist that you have an appropriate Rails gem installed too. If you install it from <span class="caps">SVN</span>, it will use the magic of <code>svn:externals</code> to stick the right version of Rails in <code>vendor/rails</code> and, if you&#8217;re using <span class="caps">SVK</span>, we assume you have enough of a clue to populate <code>vendor/rails</code> appropriately.</p> <h3>What about Edge Typo then?</h3> <p>Edge typo is currently fetching edge rails via <code>svn:externals</code>, but I&#8217;ll be switching it to the Rails 1.2 branch in the next couple of changesets, which should mean that, as soon as Rails 1.2 is released, we&#8217;ll be able to push out Typo 4.1.0 pretty promptly.</p> <h3>What does Rails 1.2 mean for Typo?</h3> <p>Over time, Typo and Rails have diverged somewhat; in part it&#8217;s because we were trying to do some stuff before Rails made it easy, and we didn&#8217;t necessarily make the same choices as Rails did, so we&#8217;ve got a pretty huge code base that&#8217;s doing an awful lot of heavy lifting that could (and should) be left to Rails. One of my goals in the next development cycle is to bring Typo more into line with the Rails way. Some things are sacrosanct of course: Article permalinks are sacrosanct &#8211; if an article has the url <code>http://www.bofh.org.uk/articles/2006/11/24/typo-on-rails-1-2</code> today, then it&#8217;s going to continue to have it for as long as you&#8217;re running typo and on the same server. And any new articles will have canonical URLs of a similar form.</p> <p>Pretty much everything else is up for grabs though. We&#8217;re going to try and keep well known URLs working but they may be redirects to a more RESTful canonical version, and we&#8217;re not about to break your feeds any time soon, but the admin urls will certainly be changing (again we&#8217;ll put redirects in for a few releases, but they won&#8217;t be supported in perpetuity).</p> Fri, 24 Nov 2006 05:00:00 -0600 urn:uuid:3d9471ee-65d5-4d78-80e6-7665302b4f9a pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/11/24/typo-on-rails-1-2#comments Typo http://www.bofh.org.uk/articles/2006/11/24/typo-on-rails-1-2 Precalculating in Typo <p>You may or may not know that Typo is multiblog capable under its hood. There is a <code>blogs</code> table in the database and every single request ends up fetching the blog object by doing a <code>Blog.find_by_base_url</code> query.</p> <p>We don&#8217;t have UI support for multiblogging though, and the <em>vast</em> majority of Typo installations have exactly one blog object. Even when multiblogging comes along, there won&#8217;t be that many blogs in any given installation.</p> <p>The problem is, the instance caching tool we&#8217;re currently using only caches objects that are fetched using <tt>Model.find(<i>id</i>)</tt>, so we end up with a basic page hit finding the blog by searching for the base url and then, later, fetching it again using the id.</p> <p>One option is to fix the caching mechanism.</p> <p>But that&#8217;s too much like hard work. So, in the latest checking on the typo trunk I&#8217;ve fixed things so that <code>environment.rb</code> builds a hash which maps from base urls to blog ids. So now, the first thing we do with any incoming request is use the hash to find the id of our blog object and then do <tt>Blog.find(<em>id</em>)</tt> <em>et voila</em> we&#8217;ve fetched our blog and populated the instance cache as well. God is in his heaven, all is right with the world, and we&#8217;re doing one less query per page hit.</p> Mon, 30 Oct 2006 02:09:00 -0600 urn:uuid:1d14d529-69ac-447c-8dcf-d83fe245b9a5 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/10/30/precalculating-in-typo#comments Typo http://www.bofh.org.uk/articles/2006/10/30/precalculating-in-typo Getting back to Typo <p>I&#8217;ve been taking an accidental sabbatical from Typo. It started during conference season, then there was a bunch of housekeeping and general home type stuff that needed doing, so I&#8217;ve been away from the codeface for a while (and I <em>still</em> haven&#8217;t turned my EuroFOO talk into a podcast, or finished scanning and uploading all the EuroOSCON photos&#8230;)</p> <p>However, I am back and coding, and a new typo feature just made it to the top of my todo list: This morning, in a fit of over enthusiasm, I managed to zap the 36 most recent comments on this blog. And, for bonus points, I didn&#8217;t have a backup.</p> <p>So, now I have a backup regime in place. And the next feature I add to Typo is going to be a confirmation box when you attempt to delete any feedback that hasn&#8217;t been marked as spam.</p> <p>Recent changes added to the typo trunk add CachedModel support, which dramatically reduces our query count per page, which is no bad thing either; I have other ideas for getting that count down too.</p> <p>So, until the <a href="http://typosphere.org/trac">Typo Trac</a> is back up, watch this space, I shall try and post here whenever there&#8217;s any significant changes on the trunk.</p> <h3>Updates</h3> <h4>Google cache is my friend!</h4> <p>Miles Barr reminded me in the comments that, as well as hanging on to all those embarrassing infelicities, Google&#8217;s search cache also remembers good things like comments that you foolishly delete.</p> <p>Sadly, it didn&#8217;t remember everything, but it did remember everything, but it did remember a lot, so various articles have their commenty mojo working once more.</p> <p>Did I really just say &#8216;commenty mojo working&#8217;? It seems I did. Ah well, it&#8217;s 6.20am and I&#8217;ve been awake since 4, I think I&#8217;ll let myself off with a caution.</p> <h4>Oops I did it again</h4> <p>But my backups just saved my arse. Now I really should get on with making sure I don&#8217;t do it again.</p> Sun, 29 Oct 2006 07:19:00 -0600 urn:uuid:913d4df2-924c-481e-b150-549687e54975 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/10/29/getting-back-to-typo#comments Ruby Typo typoupdate typo http://www.bofh.org.uk/articles/2006/10/29/getting-back-to-typo Reasons to be edgy... <p>I&#8217;ve been busy with a new experimental branch of typo that plays well with edge rails, in part because I wanted to move to a more RESTful <span class="caps">URL</span> scheme for Typo.</p> <p>But then I took a look at some of the things going on in Rails Core and my nipples exploded with delight. For instance, there&#8217;s now a <code>ResourceFeeder</code> helper that pretty much magically deals with Atom and <span class="caps">RSS</span> feeds for Rails Resources, which would allow us to eliminate a whole pile of ugliness in the Typo source. So that&#8217;s a win.</p> <p>But then, I just discovered that Rails now has &#8216;real&#8217; <a href="http://dev.rubyonrails.org/changeset/5163">around filters</a> which allow you to implement a filter as a block which calls yield. Which means that it&#8217;s now easy to write filters that clean up their resources properly, even in the face of exceptions being thrown further down the filter chain; you just catch the exception, do your cleanup and rethrow. Which allows us to eliminate a whole category of possible typo memory leaks <em>and</em> simplify a few things that are currently causing us pain. Result.</p> Fri, 29 Sep 2006 02:50:00 -0500 urn:uuid:e729c3fe-c825-44a0-a001-95efa146eb8c pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/09/29/reasons-to-be-edgy#comments Ruby Typo http://www.bofh.org.uk/trackbacks?article_id=reasons-to-be-edgy&day=29&month=09&year=2006 http://www.bofh.org.uk/articles/2006/09/29/reasons-to-be-edgy Applying design patterns unconsciously <p>I just realised something about the workings of new style Typo Sidebars: it&#8217;s just an application of the <a href="http://www.c2.com/cgi/wiki?ParameterObject">Parameter Object</a> design pattern; the <code>render_sidebar</code> helper method takes a <code>Sidebar</code> parameter object and produces a chunk of <span class="caps">HTML</span>. The fact that we persist the parameter object using ActiveRecord is almost beside the point &#8211; the persistence is more important to the  <code>render_sidebars</code> method than anything else.</p> <p>Old style sidebars couldn&#8217;t really be called an application of any design pattern. Maybe that&#8217;s what bugged me about them, they lacked the <a href="/articles/2003/07/29/the-quality-without-a-name">Quality Without a Name</a>. I&#8217;m not sure that the new sidebar architecture has the Quality either, but it&#8217;s much nearer to having it.</p> <p>When I was learning to play <a href="http://en.wikipedia.org/wiki/Go">Go</a> someone told me that it&#8217;s easier to remember professional games than those of amateurs because the moves in a professional game are generally more &#8216;right&#8217; than those of weaker players. To a good go player, the &#8216;right&#8217; move has an obvious purpose (or, more likely, purposes). Bad moves don&#8217;t.</p> <p>Maybe something similar applies to code. In good code it&#8217;s clear what each piece does &#8211; maybe it can be seen as an example of a design pattern, maybe not &#8211; and the pieces relate well to each other. In bad code, the intent and relationships are muddied. </p> <h3>Do Design Patterns Help?</h3> <p>Continuing the Go analogy, Design patterns can be likened to <a href="http://senseis.xmp.net/?Joseki"><em>joseki</em></a> &#8211; &#8216;standard&#8217; patterns of good play in the opening of the game. It&#8217;s useful to know them, but what&#8217;s <em>really</em> important, and what takes time, practice and deep study to get good at, is using and adapting them well in the <a href="http://senseis.xml.net/?Fuseki"><em>fuseki</em></a> &#8211; the opening and its wider context. You can play a &#8216;perfect&#8217; joseki in one little corner, but its influence radiates across the board and if you don&#8217;t pay attention to what that influence is and use or adapt it well, you&#8217;re screwed.</p> <p>I think the analogy to the use of design patterns in programming is fairly obvious. Don&#8217;t you?</p> Mon, 21 Aug 2006 07:33:00 -0500 urn:uuid:d7dce296-7007-4841-9611-a749c48eb89a pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/08/21/applying-design-patterns-unconsciously#comments The Practice of Programming Typo designpatterns thequalitywithoutaname http://www.bofh.org.uk/trackbacks?article_id=applying-design-patterns-unconsciously&day=21&month=08&year=2006 http://www.bofh.org.uk/articles/2006/08/21/applying-design-patterns-unconsciously Dogfood time <p>I&#8217;ll let you into a secret. You can tell when I&#8217;ve done a big <code>svn up</code> on this blog simply by looking at the theme. If it&#8217;s all black and white and sans serif, then it&#8217;s a racing certainty that I&#8217;ve just done an upgrade which has broken my usual custom theme.</p> <p>So, later today I shall be sitting down with my local theme repository and bringing things up to speed with all of Scott&#8217;s changes. Who knows, I might cheat and put back a few helper methods.</p> <h3>Update</h3> <p>Oops, it seems that there was a bug in the Scribbish theme which meant you couldn&#8217;t read articles at their permalink&#8230;</p> Sun, 20 Aug 2006 05:13:00 -0500 urn:uuid:cd887c3d-a484-485f-af89-807144d51edc pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/08/20/dogfood-time#comments Administrative Typo http://www.bofh.org.uk/trackbacks?article_id=dogfood-time&day=20&month=08&year=2006 http://www.bofh.org.uk/articles/2006/08/20/dogfood-time Cunning tricks with the new typo sidebars <p>I was going to save this until I&#8217;d rejigged my blog to a three column layout and had left everyone mystified by how I&#8217;d managed to get sidebars on both sides. But, let&#8217;s be honest here, it&#8217;s going to be <em>ages</em> before I do that. So, I shall spill the beans preemptively.</p> <p>Actually, you&#8217;ve been able to do this, or something like it for ages, but new style sidebars make it easier.</p> <p>Imagine you&#8217;re editing the layout of your new, three column theme, and you&#8217;ve got a <code>left-sidebar</code> div, which you want to populate with a tag cloud and the categories sidebar.</p> <div class="typocode"><pre><code class="typocode_default ">&lt;div id='left-sidebar'&gt; &lt;%= render_sidebar TagSidebar.new :maximum_tags =&gt; 30 %&gt; &lt;%= render_sidebar CategorySidebar.new :show_empty_categories =&gt; false %&gt; &lt;/div&gt;</code></pre></div> <p>Then it&#8217;s just a matter of styling to get the sidebar in the right place.</p> <p>This works because the vast majority of sidebars don&#8217;t hold any state apart from their settings (Certainly none of the core sidebars do) and their position in the sidebar list. So, if you want to render particular sidebars in your layout, you don&#8217;t need to go to the database at all.</p> <p>Of course, I can conceive of sidebars that will need to manage persistent state, but now I&#8217;ve realised that you can manage sidebars like this without having to go to admin/sidebar at all, I shall be working on making things a little bit friendlier. If nothing else, I should probably write a helper that lets you do:</p> <div class="typocode"><pre><code class="typocode_default ">render :sidebar =&gt; TagSidebar, :maximum_tags =&gt; 15</code></pre></div> <p>to make the interface a little more consistent with the rest of rails&#8217; suite of <code>render</code> helpers.</p> <p>Enjoy.</p> <h3>Update</h3> <ol> <li>Now that extended content is working properly again, I&#8217;ve moved the details back below the fold.</li> <li>Dan Milliron has another <a href="http://blog.emarm.com/articles/2006/08/09/multiple-sidebars-in-typo">neat way</a> of doing this.</li> </ol> Sun, 20 Aug 2006 04:18:00 -0500 urn:uuid:f408ff59-edfb-4aab-b72e-698b98fadcfb pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/08/20/cunning-tricks-with-the-new-typo-sidebars#comments Typo http://www.bofh.org.uk/trackbacks?article_id=cunning-tricks-with-the-new-typo-sidebars&day=20&month=08&year=2006 http://www.bofh.org.uk/articles/2006/08/20/cunning-tricks-with-the-new-typo-sidebars Victory! For now <p><a href="http://www.typosphere.org/'s">Typo</a> Sidebar&#8217;s are now controller free!</p> <p>Which probably means nothing to the vast majority of people reading this. But it makes me very happy.</p> <p>Until a couple of revisions ago, Typo sidebars were rendered through a convoluted route, which involved <em>n_ + 1 calls to <code>render_component</code>, where _n</em> is the number of items on the sidebar. Calling <code>render_component</code> isn&#8217;t something you really want to do even once if you can help it. It&#8217;s not as slow as it used to be, but it&#8217;s still unpleasant.</p> <p>So, now a typo sidebar looks pretty much like any other Rails plugin. It lives in <code>vendor/plugins</code> with a model, a view, a test and an only mildly clever <code>init.rb</code>.</p> <p>For the <span class="caps">MVC</span> purists among you, there&#8217;s a small amount of shenanigans involved because the model carries information about where to find the sidebar&#8217;s template, but I shall plead necessity and have done with it. Besides, the model never makes direct use of the information, it just holds onto it for the controller.</p> <p>The upshot of this, and <a href="http://scottstuff.net/blog/articles/2006/08/17/the-typo-4-1-development-cycle-has-begun">Scott&#8217;s changes</a> is that Typo&#8217;s <a href="http://www.typosphere.org/trac/browser/trunk/components"><code>components</code></a> directory is now empty. And you can call me Mr Happy!</p> <p>You don&#8217;t <strong>have</strong> to call me Mr Happy of course, but I reserve the right to be happy anyway.</p> <p>Expect a quick introduction to writing your own sidebars soon.</p> Sun, 20 Aug 2006 03:43:20 -0500 urn:uuid:8efa90ed-2a80-4796-9ddd-77c799c71f3f pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/08/20/victory-for-now#comments Ruby Typo http://www.bofh.org.uk/trackbacks?article_id=victory-for-now&day=20&month=08&year=2006 http://www.bofh.org.uk/articles/2006/08/20/victory-for-now