Monday, February 25, 2008

Time Machine Preparing

After upgrading to Leopard 10.5.2, I noticed that my Time Machine never backed up any files... it would just hang on the "preparing" mode. This is apparently a common problem with the current upgrade, so if you have run across this issue, check out this post:

http://www.macfixit.com/article.php?story=20080219115528865

None of those options actually worked for me. What I ended up doing was deleting the backup directory and letting TM just redo a full disk backup. I recommend this only as a last resort, since you will lose all historical data. But if you only use the backup as a fail-safe like I do, it's no big deal.

Thursday, February 21, 2008

Code Te Ching - Verse 44


Two Fredericks were talking.
Taylor said to Brooks:
I know of a process, the kind they call "agile."
The rules are too flexible, so lacking in specifics,
No one can make sense out of it.
A graph would be impossible.
You cannot cut it up in any way that makes sense.

There the idea sits,
No executive will look twice.

Such is your teaching –
big and useless.


Brooks replied:
Have you ever seen the wildcat
Crouching and watching his prey –
This way it leaps, and that way,
high and low, and at last lands the trap.

Have you seen the yak?
Great as a thundercloud
He stands in his might.

Big? Yes: but he can't catch mice!

So for your process. Big and useless?
Then plant it in the depths of organization
In the unfinished projects.
Walk idle around
Watch while projects finish themselves.
No executive can touch it.
No chart can ever tie it down.

Useless? You should worry!

Wednesday, February 20, 2008

Code Te Ching - Verse 43

Of the activities of the mind that exist in a vacuum
Coding is not one of them.

Does the author of a book own the story
    that his readers read?
Does the painter of a masterpiece own the scene
    that the painting evokes?
Does the carpenter of a house own the home
    that the house holds?
Neither does a coder own the function of the code he writes.

True:
    books have publishers,
    paintings have museums,
    houses have buyers,
    code has distributors.
False:
    any of these are permanent.

Stories are copied,
Images fall out of style,
Homes are abandoned,
Code is obsolete.

But who will shed a tear when code is obsolete?
Not even the author.
The ten thousand things will destroy it.

Code written has no owner.
Code written is owned by all.
Why expel effort grasping the unownable?
The result will not repay the effort.

Monday, February 18, 2008

Code Te Ching - Verse 42

Perfect numbers are an illusion
    they give a sense of control.
Perfect measures create confusion,
    they lose track of reality.

Reality is imperfect.

Thus the wise guide empirically,
not by number and measure.

Rules are for the benefit of fools
the wise need only follow his heart.

Wednesday, February 13, 2008

A Safe HashMap for Java

If I was forced to specify what I loved most about Ruby my first answer would have to be terseness. Consider the case where you want to iterate through a list of objects and generate a hashmap of arrays:
h = Hash.new

for value in list
# if the key 'foo' contains nil, populate it with an Array,
# then add new value to array under key 'foo'
(h[value.foo] ||= Array.new) << value.bar
end
That was expanded for the sake of readability, I would normally write it like this:
h = {}
list.each { |v| (h[v.foo] ||= []) << v.bar }
but I digress.

Oh, the horror that arose when I worked on a Java project again, only to run into a similar requirement - verbose beast!
HashMap<String, List<String>> h = new HashMap<String, List<String>>();

for(Thing v : list) {
List<String> ar = h.get(v.foo);
if(ar == null) {
ar = new ArrayList<String>();
h.put(v.foo, ar);
}
ar.add(v.bar);
}
I'm sure it looks familiar to most who work with Java.

So I created a safe hashmap for Java, which encapsulates the above behavior. Now the code is only this:
SafeHashMap<String, List<String>> h = new SafeHashMap<String, List<String>>(new ArrayList<String>());

for(Thing v : list) {
h.get(v.foo).add(v.bar);
}
Notice the addition of the object passed into the constructor. This object is cloned and returned if the Map contains no value for the given key.
import java.util.HashMap;

public class SafeHashMap<K,V> extends HashMap<K,V>
{
private V type;

public <T extends V> SafeHashMap(int initialCapacity, float loadFactor, T type) {
super(initialCapacity, loadFactor);
this.type = type;
}

public <T extends V> SafeHashMap(int initialCapacity, T type) {
super(initialCapacity);
this.type = type;
}

public <T extends V> SafeHashMap(T type) {
super();
this.type = type;
}

public V get(Object key) {
V value = super.get(key);
if(value == null) {
try {
value = (V)this.type.getClass().getMethod("clone").invoke(type);
super.put((K)key, value);
} catch(Exception e) {
e.printStackTrace();
}
}
return value;
}
}

There's my quota: one Java submission per quarter.

ActiveResource < ActiveRecord

I'll save you some time: ActiveResource is not a drop-in replacement for ActiveRecord. Perhaps you knew that, but I did not, and wasted half a day because of it. It looks similar, and acts similar - but don't be fooled. It will not work with any plugin that is built to work for active record (to be expected) or many plugins built to work with controllers (color me surprised), like make_resourceful or resource_this.

So, here is a list of things active resource is missing:

update_attributes

Causes update on generated scaffolds and controller plugins to break

associations

Associations are sweet methods like has_many or belongs_to. Without them, it is impossible to map any sort of ActiveResource hierarchy - so just accept that there is none.

field mapping

Should come as no surprise, but active resource cannot give you any information about the underlying REST-populated structure until AFTER it has made the call. Similar to the painful lack of associations - you cannot even dissect the ARec object.

So don't get too excited about ActiveResource. It still needs a lot of work before the dream of pure REST-driven-object-based service/client separation can exist on the scale of simplicity of the ActiveRecord pattern. Until then - you still need to manually manage your resource objects (unless they are simple) - likely via the Controller.

Update: "update_attributes" doesn't exist. Something similar exists named "load". So:
mar = MyARes.find(:first)
mar.load({:my_val => "hi"})

Thursday, February 7, 2008

How Many Rails Developers Does it Take...

Got a joke for you:

How many Ruby on Rails developers does it take to screw in a lightbulb?
Three - One to screw it in, and two to write books about it.

I wrote that as an opener to an article for DevX about my difficulties upgrading from Rails 1.2 to 2.0. But then I remembered they never paid me the last time I did work for them, so I'll just post it here (later), and they can eat a dick.

Sorry - my New Years resolution was to cut down on swearing. They can eat a penis.

But you know something that is not written about enough? Java (ha!). John Smart's new book Java Power Tools will be out in March. This 800+ page fatty contains info about every project a modern Java developer should know. You must buy this book. I'm not just saying that because I'm a contributor - I don't get residuals (I don't think) - but in the interest of full disclosure I did get paid (hear that DevX? O'Reilly pays writers). Jokes aside - John's a brilliant dude, and I can't wait to see the finished product - though in the interest in more disclosure I haven't touched Java in 6 months.

Finally: DevX - I was joking. Now pay me!

Tuesday, February 5, 2008

To My Parents

As a member of the forgotten generation - that gap between the Gen-X slackers and the post-9/11 Millennials - those of us born between 1974 and 1989 - I ask you a favor: support Barack Obama.

This man is the John Kennedy of my generation - the only hope we've ever had. Do this for me - your child - let me stop living in your shadows.

You - booming babys - who stunted my growth with a steady diet of your youth. Down my throat went stories of how you were hippies and war heros and civil rights champions and creators of love and music.

You - lucky you - who held Dr. King, and JFK, and Lennon, and Carl Sagan, and Ginsberg as your own - leaving me with Jesse Jackson, and Clinton, and Madonna, and Bill Gates, and fuck if I know any poets.

You who witnessed, live, a man on the moon - while I witnessed, live, a teacher explode in the stratusphere.

You, who forced your children to grow in a world of television, demographics, and video games - yet dare blame me for my uninvolvement in the real world, when I've never confronted real, never seen or even smelled real. You grew up when history was static in books by experts, and left me to paddle ill-equipped in the historical fluid of wikipedia.

You had art - I have remixes, remakes and mash-ups.

You leave me insurmountable problems. You watched our debt grow from 0 to 9 trillion in your lifetime. You watched the skys blacken and the globe warm - and ask why I'm not doing more to fix it? And I will - but give me the political tools.

You gave me the burden of healthcare for you and my children, leaving me to pay a social security that I will never see - leaving the country bankrupt to pay you your pittance when you retire. Security indeed.

We have no hope. But don't blame yourselves, don't cry, mom. It's not gone - hope is a feeling I've never known.

I grew up knowing the problems you caused rested upon me to fix. I know I will never retire, and my children will be worse off than you, and that technology is our last great hope - and must be built by my hands. Yet you continue to push against my ideals like open-source voting or digital medical records or electric cars.

The truth is your generation drank up all the hope and wonder and left me thirsty for so long I feel born jaded. I have nothing left to believe in but iPhones and American Idol - which are more likely to stick around than the local grocery you complain I don't buy from.

Ramen is ramen, I say.

Dear, parents - you have fought some good battles in your lives. You can stop fighting now - you won. I grew up in a time where all people are equal, thanks. It never occurred to me to make my wife a homemaker, or disregard an employee because he's not caucasian. My battles are not black versus white or young versus old or rich versus poor. My battle is simple: the past versus the future. You must understand: things cannot stay the same.

The sheer size of your generation ensures that all votes bend to your desires. I don't know if I can change your minds in time, so I ask only for a small favor. Trust me - trust your children - if only this once. Vote for Barack Obama - my chance at hope.

Please. Get out of the spotlight. It's my turn to effect change - and I need Obama.

Monday, February 4, 2008

Sunshine and AR-Extensions Make Me Faster

1. Sunshine + Warm = Happy

2. Happy => More Productive

3. More Productive => Feel Like Writing

It's 70 and sunny today. I worked at my normal pace today (rather than my previous month's frozen-snail ambulation). I feel like blogging. Who says SAD isn't real?

Quick thing today: ActiveRecord::Extensions are gold. We've used it for almost a year here, but it never occurred to me to tell anyone about it. Until it caused an error and I found no relevant info. So here's the skinny:

Normally whilst bulk-updating via ActiveRecord you create an object thusly:
data_hashes.each do |i|
Animal.create(:genus=>i['g'], :species=> i['s'])
end
This is fine, until you find yourself importing WikiSpecies. Then, let's just say, you'll be spending a lot of time on your DS. Enter: AR-Extensions. This cute hunk of hack extends the standard ActiveRecord library with loads of useful items, such as creating temporary tables, (dis|en)abling foreign keys on the fly, to_csv - but best of all is "import", which generates a bulk insert statement, rather than the standard one-at-a-time mechanism. Check it out with import:
data_as_ary = data_hashes.collect{|i| [ i['g'], i['s'] ] }
# note the array of sym's describing the data array's array values
Animal.import([:genus, :species], data_as_ary)
One big bulky import! Sexy, eh? Though I can't for the life of me figure out - why, oh, why - he doesn't let you just import an array of AR objects, and just skip the whole explaining-what-the-array-elements thing, like so:
animal_ary = data_hashes.collect{|i| Animal.new(:genus=>i['g'], :species=>i['s']) }
Animal.import(animal_ary)
Oh right - the error I ran across. If you plan to utilize AR-Extensions outside the standard confines of a Rails server (like we do, with a custom connector - calling ActiveRecord::Base.establish_connection manually - ensure you require 'ar-extensions' at the end of your config/environment.rb - and not in the file you intend to use it. Trust me - it's for the best.