You are here: Blogsphere Longtail
Keep up to date with your favourite Rails bloggers in context.
I just posted a short screencast on how to get started with Clojure and Aquamacs:
One of the fun features of Clojure, or any Lisp I suppose, is the interactive development workflow. As you can see in the video, you write code by creating expressions that define functions and then you evaluate those functions in the REPL (Read-Eval-Print-Loop). You can redefine a function at any time. You can imagine that if you had a production system running, you could connect to it via a REPL or something like that, evaluate some expressions that redefine functions that contain bugs, and the system would be fixed with no downtime.
Here's the contents of the ~/bin/clj script:
#!/bin/bash
SRC_DIR=/Users/pbarry/src
CLOJURE_JAR=$SRC_DIR/clojure/clojure.jar
JLINE_JAR=$SRC_DIR/jline/jline-0.9.94.jar
if [ -z "$1" ]; then
java -cp $JLINE_JAR:$CLOJURE_JAR jline.ConsoleRunner clojure.lang.Repl
else
java -cp $CLOJURE_JAR clojure.lang.Script $1
fi
Canon 1D Mark III
Broken mirrors and fingernails
So here's a fairly typical problem that happens in the Rails world: you have a long-running process that you need to offload/queue up, and you don't have time to fuck around with some kind of elegant solution. Before, either I'd just make the user eat it and wait for the long request (at the risk of timing out the request and/or pissing off the user), or figure out some way to procrastinate on implementing the feature in the first place.
But alas, I came to a situation that absolutely had to be offloaded: a 50MB file import that takes about 3-5 minutes to process. The request is guaranteed to time out, and it is something that will be done fairly regularly. I'd love to tell my users "Hey, this shit is going to break, but it will be the best and most awesome breaking you've ever seen," but somehow I don't think that would fly. Damn. I don't want to screw around for two days trying to cook up some kind of "scalable" solution involving worker processes and messaging queues. I don't need scalability (this will be run 2 or 3 times a week, max), I just need it to work.
When faced with a problem like this, I think web developers in general underestimate the massive amounts of thought and effort that have gone into the systems that we use every day and generally take for granted. We tend to live in our own little bubbles and think that somehow, our problems are brand new, and that they've never been solved before. Well, guess what: almost all of them have been solved before, have been solved better, and are included in almost all Unix systems out there.
atIf you have a command, and want to have it wait a tick before it starts working, and want the work of several jobs to be handled in some kind of sane fashion, at is the perfect solution. Like most things Unix, at is pretty damned simple. You have a set of commands in some kind of a file. You want to execute them at some date in the future. You send those to at: at -t 07021824 -f /path/to/my/commands. That's pretty damned beautiful.
Now, putting it in Rails is actually damned easy. I wrote a 3-line method in my ApplicationController so that I can offload any arbitrary command. Take a look at this awesome sauce:
def offload(command)
job_id = MD5.hexdigest("#{command}+#{Time.now.to_i}+#{$$}")
`echo "#{RAILS_ROOT}/script/runner -e #{RAILS_ENV} \\"#{command}\\"" > /tmp/#{job_id} &&
at -t #{1.minute.from_now.strftime("%m%d%H%M")} -f /tmp/#{job_id}`
end
Every time I need to offload some arbitrary command, all I do is pass it to offload: offload("Part.import_bom('#{massive_file}')"). Simple as pie.
Scaling? You say you want scaling? You have 3 application servers that you want to dish these offloaded processes to as equitably as possible? You are also as lazy as I am? Awesome:
APP_SERVERS = ["172.16.200.50", "172.16.200.51", "172.16.200.52"]
def offload(command)
job_id = MD5.hexdigest("#{command}+#{Time.now.to_i}+#{$$}")
`ssh user@#{APP_SERVERS[rand(APP_SERVERS.size)]} "echo \\"#{RAILS_ROOT}/script/runner -e #{RAILS_ENV} \\\\"#{command}\\\\"\\" > /tmp/#{job_id} &&
at -t #{1.minute.from_now.strftime("%m%d%H%M")} -f /tmp/#{job_id}"`
end
Now you've got your distributed job queue implemented. Three lines of code. Win.
Sidenote: If your dev machine is running OSX like mine is, and you want this to work, you're going to have to run the command sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist and restart before this stuff will work locally.
I’ve configured KNotify to work with ZenTest. To see knotify messages just drop below code to ~/.autotest
module KDENotify
def self.span str, color
"<span style=\"color: #{color}\">#{str}</span>"
end
def self.notify title, msg, color
system "dcop knotify default notify " +
"eventname '#{span(title, color)}' '#{span(msg, color)}' '' '' 16 2"
end
Autotest.add_hook :ran_command do |at|
if at.results.split("\n").last.first =~ /([0-9]+\sexamples,\s([0-9]+)\sfailures?(,\s([0-9]+) pending)?)/
message, failures, pending = $1, $2.to_i, $4.to_i
if failures > 0
notify "Tests failed", message, "darkred"
elsif pending > 0
notify "Tests passed with some tests pending", message, "goldenrod"
else
notify "Tests passed", message, "darkgreen"
end
end
end
end
My ultra-secure commenting system has finally fallen foul of the malicious robots of spammers. They're probably terrorists, hijacking the precious interblah.net-page-rank fluids to build some kind of net-bomb. Unthinkable!
Anyway, this is good for me, because it forces me to develop some new stuff to counter the spam. And the first step is being able to delete snips. Here's my quick-n-dirty dynasnip for the moment:
require 'vanilla/dynasnip'
require 'vanilla/dynasnips/login'
class Delete < Dynasnip
include Login::Helper
def handle
return login_required unless logged_in?
name = app.request.params[:snip_to_delete]
snip_to_delete = Vanilla.snip(name)
snip_to_delete.destroy if snip_to_delete
"Snip #[snip 'name' cannot be found] has been deleted."
end
self
end
I've also added the link to the template, but this in turn raises some interesting, unanswered questions about how to take Vanilla.rb from an interesting toy into a proper web platform.
0 comments for wham-bam-thank-you-spam
Yesterday I released a new version of The atom protocol exerciser. We have been working in order to simplify its architecture and create a modular system that anyone may extend.
Now it works from the command line as well the web interface. We've added some rake tasks that you can use for exercise your server implementation and you can select the output format just invoking the correct option:
$ rake ape:go:text['service document uri']
$ rake ape:go:html['service document uri']
$ rake ape:go:atom['service document uri']
It allows some configuration options through its config file $APE_HOME/aperc:
Ape.conf[:REQUESTED_ENTRY_COLLECTION] = 'collection name'
Ape.conf[:REQUESTED_MEDIA_COLLECTION] = 'collection name'
And finally, this last release allows to create and add new tests easily. The test cases must to extend the Ape Validator class and override the validate method.
module Ape
class CustomValidator < Validator
def validate(opts = {}) end
end
end
We've implemented a little system for select the variables to use in your tests, just call the requires_presence_of method into the class declaration and pass the variable name that you require.
module Ape
class CustomValidator < Validator
requires_presence_of :entry_collection #OR
requires_presence_of :entry_collection => 'comments' #OR
requires_presence_of :media_collection => {:accept => 'image/png'}
#...
Once your custom validator is ready you just need to move it to $APE_HOME/validators.
But if you really want to learn how to write your custom validator you just need to take a look at the source code.
Yesterday I released a new version of The atom protocol exerciser. We have been working in order to simplify its architecture and create a modular system that anyone may extend.
Now it works from the command line as well the web interface. We've added some rake tasks that you can use for exercise your server implementation and you can select the output format just invoking the correct option:
$ rake ape:go:text['service document uri']
$ rake ape:go:html['service document uri']
$ rake ape:go:atom['service document uri']
It allows some configuration options through its config file $APE_HOME/aperc:
Ape.conf[:REQUESTED_ENTRY_COLLECTION] = 'collection name'
Ape.conf[:REQUESTED_MEDIA_COLLECTION] = 'collection name'
And finally, this last release allows to create and add new tests easily. The test cases must to extend the Ape Validator class and override the validate method.
module Ape
class CustomValidator < Validator
def validate(opts = {}) end
end
end
We've implemented a little system for select the variables to use in your tests, just call the requires_presence_of method into the class declaration and pass the variable name that you require.
module Ape
class CustomValidator < Validator
requires_presence_of :entry_collection #OR
requires_presence_of :entry_collection => 'comments' #OR
requires_presence_of :media_collection => {:accept => 'image/png'}
#...
Once your custom validator is ready you just need to move it to $APE_HOME/validators.
But if you really want to learn how to write your custom validator you just need to take a look at the source code.
datastructures question
Early Friday
The Not So Long Tail
A friend who once commented that Wired was the Cosmo of technology news would’ve appreciated the following from the article, “Study Refutes Niche Theory Spawned by Web,” in today’s Wall Street Journal:
Faithful readers of this column might recall its own skepticism about the idea when the book first hit the stores. In retrospect, “The Long Tail” seems to have followed the template of many Wired articles: take a partly true, modestly interesting, tech-friendly idea and puff it up to Second Coming proportions.
In het kort:
The Big Word Project is redefining words. Search for your word and link it to your website. Your website is then the new definition. (more)
Ik heb toen nifty gekocht en daardoor kreeg ik vorige week een mail in de bus.
Paddy van The Big Word Project is on tour in Europa. Belgie is zijn eerste stop en ik was vanmiddag de eerste in een rij wordees (word-owners).
Omdat Karmeliet naar mijn mening het beste/betere belgisch bier is en ge moet dat dan toch gedronken hebben als toerist, zijn we er een eentje gaan drinken in het patersvatje (Antwerpen). Tof gebabbeld (er was nog een vriend en vriendin bij, namen vergeten sorry) vervolgens een klein interviewtje gedaan en nog wat tof gebabbeld :)
De mens heeft ook twitter account, spijtig dat we niet hebben gegeten, anders was het een @twunch ;)
Fijn. Internetpeeps zouden dat meer moeten doen.
Ongeveer 40 km. Dat heb ik vandaag gefietst. Straf eh!
De rest van de avond voor dood in de zetel ...
How Creationists Explain Evolution - SCARY
Writers Mugs Block Print Gallery - HOME PAGE
Coding Horror: Alan Turing, the Father of Computer Science

svn co https://marsyas.svn.sourceforge.net/svnroot/marsyas/trunk marsyas
Process Theatre
“ As usual, Ruby is 100 times slower. ”
Mauricio Fernandez
Blue Sage Realty Sucks, Apparently
이 글은 꽃띠앙님의 2008년 7월 2일의 미투데이 내용입니다.
<!-- end of daily_digest -->
Optimiser les performances d’un site web
Tahiti gets a name and an initial code push
response = Net::HTTP.get_response(URI.parse(uri_str))改成:
uri = URI.parse(uri_str)這樣一來不管是301、302,還是最該死的404都沒問題啦XD
http = Net::HTTP.new(uri.host)
response = http.send_request('GET', uri.request_uri, {"User-Agent" => "Mozilla/5.0"})
adamwiggins's rest-client at master — GitHub
Tell us what you think of the new BlogSphere feature. We are continually looking to improve and update the
functionality based on your feedback.

Find your next Ruby on Rails project or job.
Exclusive content,
regularly updated - onsite and tele-working positions listed.
I've known mark for years and enjoyed working with him.
-
C.N, United States