Alex Chaffee's blog
Upgraded to git 1.6.3 yet? You should, and Jason Rudolph says why (and if you're on a Mac, Rob Sanheim says how.)
Sadly, after you do upgrade, when you start doing "git push", your console will start to be littered with the following oddly patronizing message:
warning: You did not specify any refspecs to push, and the current remote
warning: has not configured any push refspecs. The default action in this
warning: case is to push all matching refspecs, that is, all branches
warning: that exist both locally and remotely will be updated. This may
warning: not necessarily be what you want to happen.
warning:
warning: You can specify what action you want to take in this case, and
warning: avoid seeing this message again, by configuring 'push.default' to:
warning: 'nothing' : Do not push anything
warning: 'matching' : Push all matching branches (default)
warning: 'tracking' : Push the current branch to whatever it is tracking
warning: 'current' : Push the current branch
While I'm generally in favor of verbose warnings, this one is kind of bizarre. Essentially, it's saying, "Warning! The command you just ran will continue to operate exactly as it did before!" Guys, telling us about new options is great but that's what release notes are for.
Worse, they don't provide keystroke-level instruction beyond the offhand gerund "configuring" on how to shush it. Here's the result of my 8-minute speluking inside the output of "git help config":
git config push.default matching
There, now, that wasn't so hard after all, was it?
The following monkey patch gives a bit more information in the ActiveRecord SQL logs. Instead of just saying "User Load" it also says the file and line number in your code that asked AR to perform the operation. That way you can have a hope of tracking it down and optimizing it away if at all possible.
User Load (0.2ms) views/main_page.rb:107:in `filters_box' SELECT * FROM `users`
Code after the jump. I guess you put it in environment.rb with all the other monkeys.
def capturing_output
output = StringIO.new
$stdout = output
yield
output.string
ensure
$stdout = STDOUT
end
then...
it "exits immediately from --version" do
output = capturing_output do
lambda {
Erector.new(["--version"])
}.should raise_error(SystemExit)
end
output.should == Erector::VERSION + "\n"
end
[Updated: added instructions "If you are using a widget in rails, you now need to inherit from RailsWidget"]
Erector has been around for almost 2 years now, but we've always been a little reluctant to market it heavily. One reason has been that the API was a little inelegant. Another is that Rails integration wasn't as seamless as we'd like.
With today's release of version 0.6.3, we have hopefully fixed both of those problems. With the new RailsWidget we've got a clean separation between core Erector functionality and the magic we need to make it work with Rails. We've renamed "render" to "content" so we don't conflict with the standard Rails render method. And we've changed the API for smoother lifecycle management -- the constructor is about initializing the widget, and the refurbished "widget" method is about setting it up to emit its HTML.
The bad news is that you'll have to change your existing code. The good news is there's an update guide, which you'll find below the fold in this blog post.
Please visit our Google Group to register comments or complaints, our project web site for full documentation and FAQs, and feel free to clone or fork our GitHub repo.
(Why 0.6.3 and not 0.6.0? Because we had to work through some glitches in the new deploy process with GitHub and Jeweler and whatnot. We're only human...)
Problem: every since I upgraded to Safari 4 I've been annoyed that zooming in and out seems to confuse GMail and and Google Reader. When you zoom out, GMail refuses resize its panels, leaving a big blank space on the right side; when you zoom in, Google Reader loses its button panel at the bottom of the main area if you're in a feed with a lot of entries.
Solution: go to the "View" menu and select "Zoom Text Only".
New problem: the other setting is cooler for other sites, since it magnifies images and keeps non-fluid layouts from wrapping stupidly when you really need the text to be a little bit bigger. I wish there were a way to set it per site, but it's a global setting. Oh well, no big deal, at least now I know where it is if it comes up.
First of all, fie on Apple for giving both their cloud storage service and their backup program names that are almost completely google-proof. They've recently corrected one of those by renaming "dot mac" to "MobileMe" but calling your backup program "Backup" is a great way to make it really hard to investigate. It's like, imagine how hard it would be to do a background check on someone named John Doe.
So I use the Dot Mac Backup and it works pretty smoothly, which is the second most important feature in a backup program. (The most important feature is the ability to actually restore files.) But then one day it said that to incrementally back up my "Home Minus Media" set -- the set containing my Home Folder, but excluding big-ticket items like Music, Movies, Backups, Downloads, and so on -- would require 63 DVDs. WTF?
It turned out that the problem occurred after I trashed a few old DVD rips that I had finished watching, and the culprit was the directory /Users/chaffee/.Trash. Seems like the UI was helpfully excluding it from the list of subdirectories of /Users/chaffee, it being a system file and all, so I couldn't mark it to exclude. That's OK, I think, I'm a power user, so I'll just check the box that says "Show invisible system files."
Except there's no such box. Try as I might, I can't find a way to exclude the Trash folder from the UI. I had to dig into the file system and edit Backup's own data file, as follows.
For the millionth time, cause I always forget...
Put this in ~/.bashrc:
export JAVA_HOME=/Library/Java/Home
Also, run "sudo visudo" and add the line
Defaults env_keep += "JAVA_HOME"
or else commands like "sudo gem install" won't be able to find Java.
Without the above, I got the following error (which seemed to have been run through a baby-talk filter) when running "sudo gem install rjb":
extconf.rb:44: JAVA_HOME is not setted. (RuntimeError)
I'm writing Selenium tests again, which means a lot of XPath. Here's a trick I learned thanks to this article on Push Button Paradise.
The problem is, how do you write XPath that matches one class in a multi-class element like
<div class='foo bar'>
? The standard XPath equality operator matches a full string, so
//div[@class='foo']
won't work. The solution is arcane but I promise it works:
//div[contains(concat(' ',normalize-space(@class),' '),' foo ')]
Note that there must be spaces on either side of the class name 'foo'.
Since this is quite a mouthful, I've extracted it into a helper method. Here it is in Java:
/**
* Generates a partial xpath expression that matches an element whose 'class' attribute
* contains the given CSS className. So to match <div class='foo bar'> you would
* say "//div[" + containingClass("foo") + "]".
*
* @param className CSS class name
* @return XPath fragment
*/
protected static String containingClass(String className) {
return "contains(concat(' ',normalize-space(@class),' '),' " + className + " ')";
}
From the less faq:
blah blah blah ti/te blah blah blah -X blah blah.
Also, -R makes it show ANSI color. So I put this in my .bash_profile:
export LESS=-RX
After about two years in which the only Java I wrote had a "Script" after it, I've recently started working in my old favorite language again. It was clear to me long before I made the leap that somewhere along the line Java took a sharp turn towards Scarytown. (Maybe the writing was on the wall when the "Hello World" program comprised five lines, two declarations, and a static reference, but back in 1995 we were all so excited about getting objects without C++ that our judgement was clouded.)
Anyway, I will always have a place in my heart for the old bird (picture a portly English matron with flower dress and pocketbook and floppy hat), but Stu at Relevance Blog points out why coding in Java now feels like trying to sprint with 30-pound weights strapped to my ankles.
Java is a high-ceremony language. At every turn, Java enforces a high busy-work/real-work ratio. Specifically:
- Java's checked exceptions bloat code, make components harder to use and maintain, and lead to tons of boilerplate code, each line of which is a bug-in-waiting.
- Java's new operator/constructors cannot pick a return type. The amount of code that exists only to work around this is staggering. Two entire cottage industries have sprung up to deal with this single issue: factory patterns and dependency injection.
- Java has no metaprogramming features to automate common tasks such as field accessors, standard constructors, and simple delegation.
- Primitives, functions, and classes are not first-class objects, leading to huge code bloat to deal with these types specially.
- Java's core reflection and interception capabilities are clunky, requiring tons of bolt-on technologies to make them workable, including AOP, annotations, and code generators.
That's a pretty big stink, but if you are used to it you probably can't smell it anymore.
(And that's not even mentioning the prevalent idioms of programming with massive amounts of indirection and wrappers and statics and service locators and and BigLongClassNamesThatIncludeTheirAncestry (I always say, "Do we call it a DogMammalVertebrateAnimal? No, we call it a dog!") and redundant JavaDoc on every method and...)
I ranted and spoke and even blogged about some of these issues before, but now that I'm a visitor in that world I just feel vaguely amused and sad when I see all the hoops Java programmers still have to jump through. Yeah, control-space completion is nice, but gotapi works pretty well, and at the end of the day, no matter how many curly braces my IDE inserts for me, I'd rather have my code look like this:
parse_args(["--topping", "pepperoni"])
than this:
String[] args = {"--topping", "pepperoni"};
parseArgs(new ArrayList<String>(Arrays.asList(args)))
Wouldn't you?







