Just A Summary : Tag lazyweb, everything about lazyweb http://www.bofh.org.uk/articles/tag/lazyweb.rss en-us 40 Piers Cawley Practices Punditry So... I was wondering <p>Has anyone written an Atompub client in JavaScript yet?</p> Sat, 17 Nov 2007 12:54:23 -0600 urn:uuid:fa7400ee-cf26-4bad-b862-7acda211dfe2 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/11/17/so-i-was-wondering#comments lazyweb javascript atompub http://www.bofh.org.uk/articles/2007/11/17/so-i-was-wondering Rails tip: Side effect filters <p>Some bugs are easy to overlook. One that has a habit of catching me out is a Rails filter that returns false occasionally when it&#8217;s being evaluated purely for its side effects. Here&#8217;s how I&#8217;ve started working round the issue:</p> <div class="typocode"><pre><code class="typocode_default ">def side_effect_filter return if some_conditions_not_met? ... ensure return true end</code></pre></div> <p>What happens here is that the ensure catches any return and returns true instead. The catch is that if something throws an uncaught exception anywhere, it too gets caught by the ensure and true is returned. Which may not be what you were looking for. Here&#8217;s how to fix that issue:</p> <div class="typocode"><pre><code class="typocode_default ">def side_effect_filter error = nil return if some_conditions_not_met? ... rescue Exception =&gt; error ensure raise error if error return true end</code></pre></div> <p>This catches the exception in a rescue and stashes it in the <code>error</code> variable, then the ensure checks to see if an exception was thrown and rethrows it, otherwise, it just returns true. Which is bulletproof, but ugly. Let&#8217;s wrap the ugliness up in a method:</p> <div class="typocode"><pre><code class="typocode_default ">def self.side_effect(method, &amp;block) def_method(method) do error = nil begin instance_eval(&amp;block) rescue LocalJumpError # catches an explicit return rescue Exception =&gt; error ensure raise error if error return true end end end side_effect :side_effect_filter do return if some_conditions_not_met? ... end</code></pre></div> <p>Again, not pretty inside, but all we actually <em>care</em> about anywhere else is that the interface is good and does what it&#8217;s supposed to do. Encapsulated ugliness has its own beauty. Especially if you get the interface right.</p> <h3>Homework</h3> <p>This should pluginize quite nicely, just install the method in ActionController::Base and ActiveRecord::Base and you have a very useful tool, but I&#8217;m still not sure that the method name is right, so I&#8217;m holding off on it. If someone were to come up with a bulletproof name and release a plugin, that would be wonderful though.</p> <h3>Updates</h3> <p>Fixed a scoping issue in the encapsulated version of the code. Replaced <code>yield</code> with <code>instance_eval(&#38;block)</code></p> Mon, 08 Oct 2007 07:13:00 -0500 urn:uuid:1dc6683f-9c71-4da4-9981-a9a10a941a77 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/10/08/rails-tip-side-effect-filters#comments Ruby lazyweb rubyonrails http://www.bofh.org.uk/articles/2007/10/08/rails-tip-side-effect-filters Blessed are the toolmakers <p>My dad drives a vintage Fraser Nash. I say drives, but that&#8217;s only half the battle, a large part of his Nash time is spent fettling it. It&#8217;s an old car; bits wear out, break or drop off. And because it&#8217;s an old car, you can&#8217;t just nip round to Halfords and pic up a replacement; nor can you head down to the breaker&#8217;s yard and cannibalize something else. So he has a lathe and a milling machine and a bewildering collection of tools. When he needs a part, he will disappear into the machine shop and, after sufficient swearing and/or bleeding, he will emerge with a newly made part. For dad, it&#8217;s all part of the fun of running a vintage car. If he weren&#8217;t able to do the work, the Nash would have had to remain a pleasant pipedream.</p> <p>I don&#8217;t know my way around a machine shop, except in the vaguest and most theoretical way. The tools I&#8217;ve grown up knowing to use are programming languages, editors, fine manuals and the mental tools a grounding in mathematics brings.</p> <p>So, when I&#8217;m putting a new photography business together, and I realise that a couple of the supporting software tools that I had vaguely assumed &#8216;should exist&#8217; don&#8217;t <em>actually</em> exist, I know that it doesn&#8217;t matter. I may not know Cocoa programming yet, but I know programming, so I&#8217;m confident that, like dad in his machine shop, I&#8217;ll be able to knock something up that does the job.</p> <p>On reflection, I realised that this is probably a good thing. If I can set up and run the business with a combination of off the shelf software, then it&#8217;s trivial for potential competitors to reverse engineer the business and do the same (let&#8217;s assume here that the business is a success) and I&#8217;m left competing on margin in a service industry. No fun at all.</p> <p>Being able to make my own tools gives me a competitive edge.</p> <h3>Why aren&#8217;t there more tool makers?</h3> <p>Because I&#8217;m a programer, I know that if my working environment isn&#8217;t habitable, it&#8217;s possible to fix it. I carry that approach to working with other capable software &#8211; keep typing &#8216;teh&#8217; when I mean &#8216;the&#8217;? Add a macro, autocorrect rule, snippet or whatever you want to call it to the tool I&#8217;m using and wonder if it might be a good idea to implement some kind of central repository for such things so I don&#8217;t have to repeat myself with every new tool.</p> <p>The tools to do this sort of thing are there; they&#8217;ve never been more available, and in many cases they&#8217;re not hard to use, but surprisingly few people seem to be using them. Why is that? Why do people put up with annoying software when (often) the fix is only a couple of settings away? Why are programmers so rare?</p> <p>I wish I knew. Or maybe I don&#8217;t &#8211; as long as people don&#8217;t realise how easy it is to fix/make things, I&#8217;ve got an edge.</p> <h3>Taking control of your tools</h3> <p>If you let your tools shape you, then you&#8217;re going to be awfully uncomfortable. Make a commitment to at least capture your annoyances with the tools you use most frequently. Make a note of the problems and think about what you <em>wish</em> the software would do and blog about it. Here&#8217;s a couple of stories based on some of the things I need to be able to do for my business:</p> <blockquote> <h4>Auto Slideshows</h4> <p>As an onsite picture editor, I need to run a &#8216;smart&#8217; slideshow on a secondary display while I working on images on the primary display. The slideshow should be based on an Aperture album and should automatically pick up any changes in the underlying album.</p> </blockquote> <blockquote> <h4>Auto crediting</h4> <p>As an onsite picture editor, I need my slideshow to display a credit on any images in the slideshow that weren&#8217;t taken by me. If the Credit metadata doesn&#8217;t match &#8216;Piers Cawley&#8217; the string &#8220;by <whoever>&#8221; should be added as a &#8216;watermark&#8217; to the displayed image.</p> </blockquote> <p>If you&#8217;re a programmer yourself, you&#8217;ve just given yourself a nice list of projects to be working on when you have the time. If you&#8217;re not, then you&#8217;ve just written a useful set of requirements. Tag your post &#8216;lazyweb&#8217; and if you&#8217;re lucky someone might know how to do exactly what you want without having to write a line of code, or someone else might agree that it&#8217;s something that needs fixing and actually <em>fix</em> it. If neither of those two happen, well, at least you&#8217;ve vented your frustration, and that&#8217;s not a bad thing either.</p> Tue, 05 Dec 2006 11:07:00 -0600 urn:uuid:70d18dba-df5b-4bb3-98a0-6553f96eb7dc pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/12/05/blessed-are-the-toolmakers#comments Musings The Practice of Programming Photography lazyweb practiceofprogramming toolmaking http://www.bofh.org.uk/articles/2006/12/05/blessed-are-the-toolmakers 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 Dear LazyWeb <p>I would love to be able to run a slideshow on a second screen based on a &#8216;live&#8217; album in Aperture. So, when I drop an image into an Aperture album on my primary screen, it shows up when appropriate in the secondary screen slideshow.</p> <p>I can live with having to take an explicit &#8216;publish changes&#8217; type step from within Aperture, but I&#8217;d rather not, and I certainly don&#8217;t want the secondary slideshow to stop.</p> Tue, 14 Nov 2006 07:24:00 -0600 urn:uuid:aec136af-56d4-4cfc-bff0-cd335da8262f pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/11/14/dear-lazyweb#comments Photography lazyweb photography aperture slideshow http://www.bofh.org.uk/articles/2006/11/14/dear-lazyweb Dear LazyWeb <p>I was just about to start writing a multimethod system for ruby when I realised how much I miss Perl tools like <a href="http://search.cpan.org/~petdance/Module-Starter-1.42/lib/Module/Starter.pm"><strong>Module::Starter</strong></a>. <a href="http://www.cpan.org/"><span class="caps">CPAN</span></a> has a whole suite of tools which make it at least as easy to do the Right Thing when setting up your project than it is to succumb to ad hockery. Start your project using <strong>Module::Starter</strong>, and you get a sensibly laid out that works well with standard Perl build/installation tools, a stub of your module, with the various boilerplate bits of the documentation filled in, a test directory, <span class="caps">README</span>, etc&#8230;</p> <p>It shouldn&#8217;t be impossible to do the same thing for Ruby. Most of the tools are already here. Just use the Rails generator to build a standard stub directory layout, complete with gemspec, readme, license, tests, etc. To a certain extent, the only real issue is deciding on what a sensible project template should be.</p> <p>Or maybe this already exists and I just haven&#8217;t found it.</p> Fri, 11 Aug 2006 13:32:00 -0500 urn:uuid:b4574220-0360-48a2-b4a3-218749e9401c pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2006/08/11/dear-lazyweb#comments Musings The Practice of Programming Ruby lazyweb http://www.bofh.org.uk/trackbacks?article_id=dear-lazyweb&day=11&month=08&year=2006 http://www.bofh.org.uk/articles/2006/08/11/dear-lazyweb