alias millis='perl -MTime::HiRes -e '\''print int(1000 * Time::HiRes::gettimeofday),"\n"'\'''
strip_tags is just awful
strip_tags is possibly the worst of all the builtin PHP functions. It doesn’t even remotely do what it says. It is absolutely useless on user input because it strips everything from the first “<” it sees to the next “>” so if your input is
"<p>I <3 Monkeys</p>
its output is
I
!!! And what else are you stripping tags from apart from user input? Avoid.
badmatch CRASH REPORT couch_file:init/1
I got this Couch DB crash running a view:
Error: EXIT {{badmatch,[]}, [{couch_query_servers,new_process,3, [{file,"couch_query_servers.erl"},{line,472}]}, {couch_query_servers,lang_proc,3, [{file,"couch_query_servers.erl"},{line,462}]}, {couch_query_servers,handle_call,3, [{file,"couch_query_servers.erl"},{line,334}]}, {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,578}]}, {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,227}]}]}
This is caused by “language”: “JavaScript” in the view. It must be “javascript” (case sensitive) or omitted for javascript queries. Not sure where I copied that from.
Loading Dependencies in PhantomJS without using a Webserver
We run our javascript QUnit unit tests “headless” using the amazing PhantomJS. Originally our dependency loading code was overridden as a no-op within the tests. But that began to cause problems and require tests to run in a certain order and other Bad Things.
Within the WebPage environment in PhantomJS it is possible to form <script> tags and load code from a webserver, but not so easy to keep things running entirely from the commandline. Especially when you also want to run the same tests in the browser in QA (not everything that passes in WebKit passes in IE8, as if you didn’t know that).
To make this work I overrode the dependency loading code so that it just stores strings of dependencies in a variable xq.required
. Then:
... // Load the tests. for (var i = 0; i < sources.length; i++) { _.page.injectJs(sources[i]); } // Now that we've loaded some tests we will have registered some // dependencies (with require calls in the page). Load the // dependencies, recursively if they themselves have dependencies. _.loadDependencies(_.page); ... // Loop over the known dependencies and load them. Also load any of their // dependencies and so on, turtles all the way down. _.loadDependencies = function(page) { var loaded = []; while (true) { // Ask the page what dependencies it has toLoad = page.evaluate(function () { return window.xq.required; // executes inside page, not phantom }); // Diff toLoad with loaded to get stuff that hasn't been loaded yet toLoad = toLoad.filter(function(i) { return (loaded.indexOf(i) < 0); }); if (toLoad.length === 0) { break; } // Load the stuff that hasn't been loaded yet for (var i = 0; i < toLoad.length; i++) { _.loadByNamespace(page, toLoad[i]); } // Add what we just loaded to the list of stuff we've already loaded loaded = loaded.concat(toLoad); } }
Where loadByNamespace
converts its second argument to a file path and loads it into the first argument with page.injectJs
.
Now all the dependencies are loaded we can run the tests and report the results.
Google Street View Image API
One of the many cool APIs available through Google Maps is the Street View Image API. This gives you full access to the images taken by the Google vans that photograph streets.
The API is dead simple in the basic form, just a URL:
http://maps.googleapis.com/maps/api/streetview?size=WIDTHxHEIGHT&location=LOCATION&sensor=false
(The required “sensor” param tells Google if you are getting the location from a GPS device or similar – probably a privacy thing.)
The images are not necessarily spectacular brochure shots:
http://maps.googleapis.com/maps/api/streetview?size=400x400&location=Parliament+Square,+London&sensor=false
but it is a useful API for any app that is displaying places that a user might not have been to before. It can both give them an idea of it’s the kind of place they are looking for and help them find it. Here’s an example, a local keycutters:
http://maps.googleapis.com/maps/api/streetview?size=400x400&location=Timpson,+Victoria+Station,+London&sensor=false
Forgotten Experience
CoffeeScript Web App Framework
I’ve been working on a CoffeeScript web app in RailwayJS which is a rails-alike framework for nodejs built on top of Express.
One cool thing about RailwayJS is that you can write most of your code (not views?) in CoffeeScript instead of JavaScript. The generators, etc. will do the right thing if you give them the --coffee
switch.
RailwayJS also has ORM with MongoDB and localization baked in.
#!/usr/bin/env coffee app = module.exports = require('railway').createServer() if not module.parent port = process.env.PORT or 3000 app.listen port console.log "Railway server listening on port %d within %s environment", port, app.settings.env
History (Again)
[bakert@fenchurch ~]$ history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head 24899 git 9575 vi 7366 cd 3929 ls 2517 php 2162 mate 2125 rsync 2022 cat 1950 ssh 1938 make
Compare to four years ago. New: git, php, mate, rsync, cat, make. Climbers: ls. Same: cd, ssh. Fallers: vi. Old: u, ruby, svn, td, mysql, gd.
Newlines at the end of files
For
- If you cat a file without a trailing newline your prompt may appear at the end of the output instead of flush left.
- Some C++ compilers complain when there is no trailing newline.
- Each line in the file ends in a newline.
wc -l
reports an incorrect result if it is missing- More reasons
Against
- git considers a trailing newline a whitespace error.
- Trailing whitespace is easily lost when, for example, exchanging patches via email.
- A newline after a closing “?>” in PHP can cause problems with
header()
(although closing tags are no longer required in PHP). - It uses one more byte.
You Know You Are Trying to Do Too Much in a Bash One-Liner When …
find ~/bazel/src/main/webapp/lib -type f | grep -v "lib/deps/" | grep -v "lib/ext/" | grep -v "XG_MessageCatalog_" | xargs -I{} -L1 sh -c "echo {}; phpcs -d memory_limit=1024M -p -n -s --standard=/Users/bakert/Desktop/BazelCodingStandard {}"
Edit: Better:
#!/bin/env ruby BAZEL_HOME = '/Users/bakert/bazel' STANDARD_PATH = '/Users/bakert/Desktop/BazelCodingStandard' VERBOSE = false def main exclude_patterns = [ /XG_MessageCatalog_/, /\/lib\/deps\//, /\/lib\/ext\// ] files = Dir.glob("#{BAZEL_HOME}/src/main/webapp/**/*").reject do |f| exclude_patterns.any? { |p| f.match(p) } \ || ! File.file?(f) \ || File.extname(f) != '.php' end files.each do |f| puts f if VERBOSE print %x[phpcs -d memory_limit=1024M -n -s --standard=#{STANDARD_PATH} #{f}] end end main