Sunday, December 28, 2008

Yes Man

If you plan to see Yes Man and enjoy it, then don't read what I'm going to say.

It's funny, but there is a distractingly huge amount of paid placement in it. There are subtle things, and I realize that if people are using phones, it doesn't make sense to cover up what they are. That's fine. I'm not talking about that. I think someone had a Blackberry, but it wasn't really in my face. I'm talking about Jim Carrey looking right at the camera and saying "Rolling Rock."

Here were the most blatant offenses:

Rolling Rock- In a completely unnecessary scene-let, Jim Carrey orders a Rolling Rock specifically. And drinks it later.

Tempur-Pedic Beds- He actually goes through the process of ordering a bed, repeating the red wine jumping thing, and is way too excited about the whole experience.

Red Bull- Jim Carrey spends all night partying with friends on Red Bull. He says Red Bull somewhere between 10 and 10,000 times. What's worse is that the scene isn't even shown except for him apparently meeting a minor character during the night who later gives him--

Some motorcycle- Can't remember the name. But I remember that it "Has a LOT of torque!" So much so that bare-assed Carrey can't help but alternate between front wheelies and back wheelies.

Dell Computers- This one is almost ok. Jim Carrey is sitting at his desk writing an email. The camera is behind the monitor, and I can't recall whether the focus is on him or the logo. Either way, it was blatant.

A couple of movies- 300 and Saw. He rents them and watches them. He appears very lonely when he's watching them at his house... ok. But why did he have to flash the DVD to the camera in the video store? Absurd.


It was very close to being a movie about meeting an impossibly hot, young, spontaneous girl with lots of interests and making life an adventure. There were a couple of really good moments, but all of the product placement is too hard to ignore.

So overall, I have two complaints. One is that the movie is that product placement cheapens the movie and makes it way tackier than it could have been. Two is that I felt like the advertisers should have bought my ticket. I mean, I must have watched at least 15 commercials.

Thursday, December 25, 2008

Hard Stuff in Ruby- Part 2: Blocks

So in Hard Stuff Part One we covered some basic metaprogramming tricks. Here, we'll take care of another topic that is a little complicated at first glance, blocks.

It's really not so bad though. But they seem complicated, but just like methods, there are only two places to look at, the method call and the method declaration. That said, there is still some new stuff in both places. Let's take a look at the most common iterator method, each, that "take a block" as a parameter first. This takes care of the "method call" portion.

This is from the ruby docs:

a = [ "a", "b", "c" ]
a.each {|x| print x, " -- " }

Produces:

a -- b -- c --

So |x| is the "block parameter." This has a special context inside of the each method. But what is it doing with the x? So it must be looping through the array somehow, and updating the value for x. Where is this happening? In the method declaration for each:

VALUE
rb_ary_each(ary)
VALUE ary;
{
long i;

for (i=0; ilen; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
}
return ary;
}

There it is, in C. That explains the "rb_" thing for ruby methods. But there's really not much to it. It takes the array as the parameter, loops through it and yields the element to the piece of code that is calling it.

You can also define your own Proc objects with Proc.new and call that Proc with Proc.call. This lets you define a chunk of code that can be reused at different places in your program. Sounds a lot like a method. What's the difference? Well, it's actually an abstraction of a method. So you can use it to make methods. The documentation example is pretty clear.

def gen_times(factor)
return Proc.new {|n| n*factor }
end

times3 = gen_times(3)
times5 = gen_times(5)

times3.call(12) #=> 36
times5.call(5) #=> 25
times3.call(times5.call(4)) #=> 60

Nice. Sort of like a template for methods.

How can I use blocks in Tasker? Well, the problem is how to select a random key in a hash where the values are the relative likelihood of being chosen.

My solution so far has been this:
  
def die_roll(hash)
arr = hash.collect { |x, y| if y and y['weight'] then
a = []
y['weight'].times do
a.push(x)
end
a
else
x
end
}
arr.flatten!
return arr[rand(arr.size)]
end

But I think I can clean it up a bit. Let's clear out the conditionals and see what happens.

def random_from_weighted_hash(hash)
arr = hash.collect { |x, y|
a = []
y['weight'].times do
a.push(x)
end
a
end
}
arr.flatten!
return arr[rand(arr.size)]
end

Oddly, when y is blank, x still gets pushed onto a. But if y['weight'] is nil then the program throws an error. Ok. So let's just define the shell of nil.times as the following.

def nil.times
end

That takes care of the error, but we still have a problem. Now either setting the time but not the weight OR setting the weight as blank will result in the task not being added to the array. What to do...
How about this?

def nil.times(&block)
1.times(&block)
end

Sweet. So nil.times is a method that takes a block as a parameter and passes that block to 1.times.

That's all for now.

Hard stuff list:
-Metaprogramming
-Blocks
-Lambdas
-Singleton
-Method Missing
-eval methods
-bindings

Tuesday, December 23, 2008

Happy Holidays everyone... I think

Merry Christmas Eve to some. Happy 3rd or 4th day of Hanukkah to others. Happy Muharram Muslims. Enjoy Friday Kwanzaa celebrators. Hope all the witches, wicans, pagans, and druids had a great solstice. Don't work too hard preparing for "Demon Revels" and "Grand High Climax" you Satanists.

And from Asia (and colleges), this time of the year could be hard on you Buddhists, not having any holidays around this time and all, but I have a feeling you're fine with it. Hindu folks are in the same boat. Oh dear me, I almost forgot the agnostics and atheists. Enjoy your time off.

Umm.... And to all a good night!

Hard Stuff in Ruby- Part One

The title is a little misleading here. This "Stuff" is not necessarily hard. It is necessarily in Ruby, but could very well be in other programming languages, although perhaps not as pervasively. I have a running list of these things that I feel like I should understand better about Ruby. I'm not claiming expertise on any of the topics. I'm just taking a minute to get to know them better.

Here's the list:

-Metaprogramming
-Blocks
-Lambdas
-Singleton
-Method Missing
-eval methods
-bindings


I'll start with metaprogramming. The big idea here is that you can modify classes on the fly. Might not sound too exciting at first... But here are two simple ways that you can use it to great effect.

Let's say that you want to work with time. This can be a little tricky because you have to work with ints, maybe floats, and Time objects. Let's say you get the current time like so

Time.now

Great. Now you want to add a second to it.

Time.now + 1

Okay... How about 1 minute?

Time.now + 60

Already things are starting to get ugly... but let's go one step further. Add 3 hours 24 minutes and 32 seconds

Time.now + 3 * 60 * 60 + 24 * 60 + 32

Okay... so that works... it's a little ugly though. Metaprogramming to the rescue:

class Fixnum
def minute
self * 60
end
def minutes
self * 60
end
def hour
self * 60 * 60
end
def hours
self * 60 * 60
end
def second
self
end
def seconds
self
end
end

Time.now + 3.hours + 24.minutes + 32.seconds

Much more readable and easier to work with. I don't know if the "seconds" method should be there, given that it's not doing anything really. But it seems better to keep it consistent. Honestly, I'd rather add 32.seconds to a Time object than 32. So extending the Fixnum class is handy anytime you need a DSL for something involving numbers. Opens a lot of interesting possibilities: Conversion between base systems and music DSL's come to mind.

Second up is something that I haven't used before, but it looked like good voodoo, and I know a couple of places where it will come in real handy, real soon.

Let's say that you have an object that might get instantiated and might not. This, like the Fixnum thing, is another issue that I've run across in Tasker. The problem here is that I don't think that I should have to define the weights and times for my tasks. They should default to something. I'm reading in from a yaml file, so the task info is stored in a multidimensional hash.

I ended up writing this code to avoid the nil time:

if hash[key] and hash[key]['time'] then
time = hash[key]['time'].to_i.hours
else
time = 1.hour
end


But here's what I'll change it to very shortly.

def nil.[]; 1; end
time = hash[key]['time'].to_i.hours


Much cleaner and smarter. So that's all there is to... nope. Actually, there's a lot of interplay between the hard stuff topics, so the next hard stuff section will be Metaprogramming + X. After that is Metaprogramming + X + Y.


A couple of notes:

Other examples of simple metaprogramming are the attr: decorators found all over the place in ruby. You see them a lot in rails's yourmodel.rb files.

For more on metaprogramming, I would recommend this. My nil.[] method borrowed heavily from his nil.name method.

Monday, December 22, 2008

Tasker 2.0

Alright. So I worked out a few things with Tasker. The tasks (names and times) are now stored in a yaml file. I thought about storing them as objects, but I haven't worked with yaml much, so I thought I might give it a shot. It seems to support variable times well now, but as far as weighting things to make them more or less likely... I've had this come up before on simple projects involving probability, and I'm not quite sure how to deal with it.

Once things are in an array, it's easy enough to just select one of them:

[task1, task2, ...]
return arr[rand(arr.size)]

Sweet... But to work in the weights, I feel like I have two basic options.

Option 1 Array with repetition:

[task1, task1, task1, task2, task3, task3]
return arr[rand(arr.size)]

Option 2 Hash/multidimensional array:
{task1 => {weight => 3}, task2 => {weight => 1}, task3 {weight => 2}}
return ???


Because it loads a yaml file, the first half of option 2 is taken care of. I figured that if I could get it into the other form, it would be easy, but it is not going as expected. The collect method let me down as follows:

arr = hash.collect { |x, y| if y and y['weight'] then y['weight'].times do x end else x end}
=> [4, "Matz Translation", "FFVI", "Practical Ruby Projects", 3]

What's going on here? It looks like collect won't work a little harder for me... It only wants to return once per key. Hmm.... well, if that's the case, how about I return a little baby array?

arr = hash.collect { |x, y| if y and y['weight'] then a = []; y['weight'].times do a.push(x) end; a; else x end}

Sweet. Everything there that I wanted... now all that's left is:

arr.flatten!

Nice. Now I can just use my random index of array code again.

Sunday, December 21, 2008

Because I said so

Whatever someone is making you do usually sucks. Mowing the lawn sucks. Going to bed sucks. Cleaning your room... well, you get the idea.

But this is "because I said so" applied to chores. Applied to video games, this "because I said so" is the key to fun in my book. Why don't I just call it BISS for short. Everyone else seems to be making up acronyms, so I'll just go ahead and take ownership of this one.

I like my games BISSy as all get out. Smash Brothers is a great example. You can pair characters from completely different worlds together. It's up to you, and it doesn't have to make any sense. Yoshi fights Marth. Bowser fights Link. Princess Peach fights Princess Zelda. Where else can you go for that kind of Princess on Princess action? Sure, you pick characters because they are "good" to "win," but additionally, the game gives you permission to do things that don't make sense, and that in itself feels good. Imagine if the people that you played against insisted that vs. matches be reasonable, or the game inserted a backstory about, say, how Mario and Luigi had an argument about the electricity bill before you could fight them together. It would be vexing to say the least.

A minimal backstory, however, is another way that this can work well. Take NES's Blaster Master. You're a kid. You have a pet frog. You jump down a hole to chase him. You find a tank and some sleek futuristic armor that fits you. You hop in the tank and start shooting mutants. Your radioactive pet is the first boss. You kill him. There's no crying scene, no girl telepathically calling your name, no king pleading to save the world. There is no reason to go on, except... You have a tank and you can shoot mutants and soon your tank will fly and ... You don't motivation from the story line. You forgot about the frog as soon as you started killing stuff. The game told you to play in this weird world where you have a tank. BISSy permission to be arbitrary.

FFX2... This game had one great BISS point and one grossly misused BISS occasion. Dress spheres. Magical orbs or something that let you change clothes... and abilities! What? That's... weird... whatever, fine... cool. Grlpwr! Okay great. But what about the airship action? From the first FF game, one of the best things is getting to fly around the world. The fun in that is looping the world 6 times, spinning in circles, and eventually, deciding to go somewhere. FFX2 automated the airship experience with what amounted to a menu of destinations? WHAT? Here's a case of "you can't BISS," and not "you can BISS." That sucks. It's a rule to confine the world, not to allow players to act arbitrarily.

This game suffers from something much worse though. And it didn't take me long to stop playing for this reason. If you don't use a walkthrough, you will disappoint yourself. Why? Because you will miss out on your maximum chance to be arbitrary. You will not get every dress sphere, and your chance to switch outfits and abilities goes out the window. I don't know who to fault for this. I guess it makes money for websites and player's guide publishers. The games can promise 600 hours of searching every unmarked location searching for the elements that allow you to play arbitrarily. This is backwards. Through the course of the game, you should automatically be able to do more arbitrary things, but "missing" a chance to have maximum arbitrary power later is criminal.

In FFVI, you could kill Shadow, and not mix him with your characters later. This is the same thing, but it is ONE thing. And it is a binary choice. Wait or don't wait. I don't remember if I killed shadow the first time, but it's an easy thing to remember not to do again. If you were missing any Espers, you just went out and found them whenever you wanted. No problem. Not like FFX2. You miss it, you save, and the world has changed enough that you have no second chances. Horrible. Given a choice between having to search every nook and cranny to maximize game enjoyment later vs. "playing" a game glued to a walkthrough, I'll choose neither.

So what is good? The power to be arbitrary. Games that give that power are much more fun to play. So are instruments, actually. A controlled vibrato (or tremolo on some instruments), which is a pitch fluctuation, goes beyond being a mark of musical training. It is fun to do. It says "I own this." In language, there is fun to be found in the arbitrary. People develop code words, pet names, and inside jokes to strengthen bonds. It makes you feel important. Screw English, I'm making up my own words. Aren't I special? Meta-programming... the list goes on.

I think I get why parents tell kids that they can be astronauts.

This is only half the story though. A pursuit to be arbitrary ends up looking amorphous, blobby, or jack-of-all-trades-ish. A lot of times, I have the impetus to do something, but it's my nature to try to solve it. I spend hours contemplating the pros and cons of doing one thing or another. I chart the paths, I imagine all possible futures. This is a horrible anti-solution. I don't need to take the best course of action, just some course of action. The best will usually reveal itself later, but there is no use waiting for it and doing nothing in the mean time. I think my solution gives a nod to both the power of the arbitrary and the BISS principle.

The strategy is below:

Now Stuff and Future Stuff:
Gmail todo lists. Always accessible. Clean. Categorized

Everyday stuff:
Thought of tracking this on a calendar, but it was overkill. I just wanted a simple tool that would tell me what to do. Tasker just takes a list of longish term goals that I have, and picks one of them for me to do. For now, it just tells me to do it for an hour, and then gives me another task in an hour, but I think that there is a good deal more that can be done with this.

Namely, the time could be variable(maybe semi-random) for a given task, or depending on how important the task was to me, it could get different weights to increase the likelihood of being chosen.

Or maybe I'll just leave it alone, of course, that is until Tasker says that I should work on it.

Creepy...

Thursday, December 18, 2008

The Last Last Straw

Ok Linux. I gave you a fair shot. I put up with learning a lot of new stuff, actually, that was a good thing. Rather, I put up with having to learn a lot of new stuff. Don't get me wrong. It isn't all bad. When I am developing, the only thing I ever get jealous of on another os is textmate. Other than that, nothing. The tools are familiar and functional. So as a development platform, I enjoy it very much. But should I try to entertain myself, woe be my weekend.

But I guess in a way, that was probably good for me. I ended up troubleshooting instead of watching DVD's. That's okay. I can live without DVD's. It's pretty annoying to spend 2 days on a problem and then decide that you'd rather live with the problem than solve it. It's kind of the "Our Princess is in another castle" feeling, except not as fun. However the jumps in World 8,1 usually straight kill you just the same. Okay, so the metaphor is a little off track, but you get the idea. Maybe there's some merit in getting no payoff for a weekend of being sure the solution was right around the corner though. Probably good for you... very zen.

More concretely, here are the things that have really bothered me, but fixing them seemed like it would take a few hours/days I never really wanted to spare.

1. .doc- This one is a killer. I would LOVE if everything was open document formats, or rather, I wouldn't care, so long as it was easy for me to... oh... I don't know, do something weird like... write a resume? A lot of places prefer doc to pdf. And yeah, I know that there are ways to contort your system using wine and a *legit* copy of word... because I said, "free windows, screw that, but yes I will be paying for a word processor." Absurd. I don't care who figures this out, but someone should.

2. My friend messaged me "Hey Evan, China is launching a space shuttle. It's streaming live at somewebsite.com!" I tried to fix streaming video countless times before to no avail. Before I got a tv, I was relying on my computer for news stuff. Luckily, I got to see the pres/vice pres debates, but there have been a lot of times where I'm disappointed by the how well my system "just works," even after hours of configuration.

3. DVDs. Old ones work, but not new ones? Region this, format that. Got the Simpson's movie for Christmas last year. My computer didn't like it because it was too new, and my DVD player didn't like it because it was one of those furry barbarian Western DVD's.

4. No support for my XD picture card. I was making a birthday video for a friend in Japan, and nope, no way to send it. I had never used my card reader before, so I didn't know that it wouldn't work. I just can't trust parts that are untested, and that bothers me. Well damnzers. I guess I need an external card reader to.... wait, no, that's idiotic. I have a card reader on board. I don't need another piece of hardware to trip over.


I guess other than that, everything works pretty well. It has a few things that make it terrible as my computer, but it has a lot of things that make it great as one of my computers. I think that's the key.

Wednesday, December 17, 2008

Can't freeze rails on Heroku


Well, this is not something I expected. I suppose a lot of people would figure it out quickly enough, but it's really something they should say outright.

In my previous post, I basically said, Heroku told me to change rails versions, so I did, and then went on about fixing all of the things that broke in my code. Then, I talked with someone who said "just freeze the rails version." That sounded like a fantastic solution, the rails version would run local to my application, and it wouldn't matter what versions of rails Heroku had installed. Fantastic news. This won't break any gems not supported by earlier versions of rails (2.1 and... ). Except, it doesn't work.

This post covers the topic well. His point that the error is cryptic is well taken, but it's worse than that. We're talking about errors, not error. So his suggestion of Heroku issuing a "Don't Freeze Rails!!!" warning is especially prudent considering that his error and the one I got are not the same.

His:

MissingSourceFile in DashboardsController#index

no such file to load -- sqlite3
RAILS_ROOT: /mnt/home/userapps/xxx


Mine:

Mysql::Error in MyController#index

Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
RAILS_ROOT: /mnt/home/userapps/47584


I don't know why the errors are different. Different frozen versions? Either way, I guess it's back to figuring out how to retrofit my app...

Translation


For the past month or so, I've been translating the ruby language designer Matz's blog. It has been an interesting project, good for my Japanese, and I feel like I'm getting to understand Matz a little better.

A lot of his blog centers around his itinerary. He writes about how busy he is, who he meets and what events he attends. But a few posts so far that have stood out for me are below.

He had one about taking his kids to Vogel Park, which is apparently full of flowers and birds. It sounds like a really cool place, and next time I'm in Japan, I really want to check it out.

In another family related post, he talks about a nice thing that his daughters did on his wedding anniversary. Basically, following the model of a children's book that they had read, they made a scavenger hunt for their parents with a homemade pastry at the end.

In another post, he describes his use of "Nice Try" at RubyConf which was directed at the Rubinius project. At the time, he did not realize the cocky, sarcastic connotation (totally the opposite of his personality) of the phrase, so he was surprised when people laughed.
He posted in English and Japanese to explain this one.

I have definitely found an all new respect for professional translators. There are so many challenges and decisions with going from Japanese into English. Here's a list of what I've run into so far:

1. Missing gender information- Suzuki-san is less descriptive than Mr. Suzuki. So I either have to guess or find out by other means. Also, in general, Japanese refers to people by gender (she, her) less often than English.

2. Place/City/Company names- These aren't in the dictionary. Something like "Vogel Park" was easy enough to sort out with a google search. The name of some restaurant in Sapporo is a little harder to figure out.

3. Readings for names of people/places- There are some conventions for this, but it can also be irregular. If someone is particularly famous, a biography will probably spell out the reading though.

4. Too much indication of the ambiguity of the situation- It seems like there are a hundred ways to indicate "I wonder/maybe/possibly" in Japanese. But unlike English, it apparently is A-OK to mix them all together. There is so much wishy-washiness in Japanese that if you really wrote all of it down it you would end up with things like, "What should I do, I wonder..."

5. Missing subjects- AGH! These are all the same in Japanese:
What should I do? What should you do? What should we do? What should they do? What should he do? What should she do? What should be done?

6. Caveman-ness- There are occasions when we leave off certain things. Sometimes in a list- "Buy milk. Feed cat. etc." But partly due to subject dropping, it's hard to tell where this begins in Japanese. If there is no verb or copula at the end, then what gets cut in the sentence? There's already almost a guarantee to be no subject in the Japanese, but do you put it back in?

7. Voice- Character is a difficult thing to get right. What may sound playful in one language, might sound silly or aggressive in another. And how do you decide when to pull out the big words? Matz seems to be friendly, warm and accessible. I can't help but worry that after I translate him, he sounds too much like me though. Would he use all of the contractions, "really"s, and "a lot"s that I have him saying? I'm not sure. Also, he's undoubtedly very smart, but I feel like my translations don't necessarily reflect that. Distinguishing scholarly from common Japanese must be a product of a great deal of context and experience that I don't have to draw on.

8. Politeness- Although it's thought to be one of the major differences between English and Japanese, luckily, I don't really have to deal with it much. He may describe conversations, but so far I have come across little to no quoting of them.

Monday, December 15, 2008

Living in Cambri... okay Somerville


While I really enjoyed my time in Japan, one of the things that I never really got over was how little was expected of me. Being white, people don't really expect you to know much about the language or culture. Actually, even after living there a year, people still expected me to be perplexed by chopsticks... the things that I used TO EAT... EVERYDAY.

I've read my share of Paul Graham essays, and one that really stuck with me was called Cities and Ambition. He says that being in LA makes you want to be hip, and being in New York makes you want to be rich. Living in Cambridge makes you feel like you have to step it up intellectually. I've never spent too much time in New York or LA, so I can't attest to the first two, but dead on with the third.

At one point he describes the feeling as being in the air. It really is amazing and I don't know quite how to describe it, except to say this. When I was little, I wanted to be an actor or ninja (ninja-actor or actor-ninja was aiming too high I guess). Now... with reading through the SICP Book, I have the oddest feeling that I want to be lambda man. I might be daft.

Subject Lines

Subject lines are always the last thing I type in an email. I get everything how I want it, and then it's time to screw it all up with an awkward "hey" or "what's up?" For personal emails they never really seem to work. Sure, a "ROFL" or "Your order status" is to the point enough, but how do you summarize things that are a little more subtle? You don't actually want to summarize it, you want it to be taken in as a whole, because it would seem a little abrupt to just give the point away. Anyways, I'll try to give subject lines for a few things to demonstrate.


Dear Madam,

Subject: Sorry...

I have been shown in the files of the War Department a statement of the Adjutant General of Massachusetts, that you are the mother of five sons who have died gloriously on the field of battle.

I feel how weak and fruitless must be any words of mine which should attempt to beguile you from the grief of a loss so overwhelming. But I cannot refrain from tendering to you the consolation that may be found in the thanks of the Republic they died to save.

I pray that our Heavenly Father may assuage the anguish of your bereavement, and leave you only the cherished memory of the loved and lost, and the solemn pride that must be yours, to have laid so costly a sacrifice upon the altar of Freedom.

Yours, very sincerely and respectfully,

A. Lincoln


Paris, December 1795

Subject: Miss you like woah!

I wake filled with thoughts of you. Your portrait and the intoxicating evening which we spent yesterday have left my senses in turmoil. Sweet, incomparable Josephine, what a strange effect you have on my heart! Are you angry? Do I see you looking sad? Are you worried?... My soul aches with sorrow, and there can be no rest for you lover; but is there still more in store for me when, yielding to the profound feelings which overwhelm me, I draw from your lips, from your heart a love which consumes me with fire? Ah! it was last night that I fully realized how false an image of you your portrait gives!

You are leaving at noon; I shall see you in three hours.

Until then, mio dolce amor, a thousand kisses; but give me none in return, for they set my blood on fire.

-Napoleon


August 15, 1846

Subject: Baby, I'm gonna fuck you so hard

I will cover you with love when next I see you, with caresses, with ecstasy. I want to gorge you with all the joys of the flesh, so that you faint and die. I want you to be amazed by me, and to confess to yourself that you had never even dreamed of such transports... When you are old, I want you to recall those few hours, I want your dry bones to quiver with joy when you think of them.

-Gustave Flaubert


To Adele Foucher

Subject: <3

My dearest,
When two souls, which have sought each other for,
however long in the throng, have finally found each other ...a union, fiery and pure as they themselves are... begins on earth and continues forever in heaven.

This union is love, true love, ... a religion, which deifies the loved one, whose life comes from devotion and passion, and for which the greatest sacrifices are the sweetest delights.

This is the love which you inspire in me... Your soul is made to love with the purity and passion of angels; but perhaps it can only love another angel, in which case I must tremble with apprehension.

Yours forever,
Victor Hugo (1821)


15 August, 1904

My dear Nora,

Subject: Miss you :(

It has just struck me. I came in at half past eleven. Since then I have been sitting in an easy chair like a fool. I could do nothing. I hear nothing but your voice. I am like a fool hearing you call me 'Dear.' I offended two men today by leaving them coolly. I wanted to hear your voice, not theirs.

When I am with you I leave aside my contemptuous, suspicious nature. I wish I felt your head on my shoulder. I think I will go to bed.

I have been a half-hour writing this thing. Will you write something to me? I hope you will. How am I to sign myself? I won't sign anything at all, because I don't know what to sign myself.

-James Joyce

Sunday, December 14, 2008

A few things to note about Heroku

First off, Heroku is amazing. Free hosting for rails apps with an editor that is actually better than what I usually use. (Looking forward to Textmate after I switch to mac though...) I initially had a couple of problems getting started with it. The tarball files did not import as anticipated. I couldn't really figure out why. The git option seemed a little better anyways, albeit a few extra steps. Importing with git was still pretty trivial.
gem install heroku

heroku clone untitled-b93f9c
cd untitled-b93f9c
[..local edits..]
git add .
git commit -m "local changes"
git push
So that's way simple, and the directions are there as soon as you fire up your app for the first time. Despite this nicety, however, I came across a couple of other issues.

First, the rails version. Heroku likes 2.0.2, or 2.1. I was running with version 2.1.2. So that just involved changing
RAILS_GEM_VERSION = '2.1.2' unless defined? RAILS_GEM_VERSION

to
RAILS_GEM_VERSION = '2.1' unless defined? RAILS_GEM_VERSION

in config/environment.rb.

Naturally, changing the rails version made some of my other packages squeal. Thoughtbot's Clearance authentication system, makes use of Digest::Sha1. This apparently does not come prepackaged with Rails 2.1, so another change to enviroment.rb fixed that:

#Put the sha BACK!
require 'digest/sha1'
Next, a :link_to method caused a problem:
<div id="app_name">
<%= link_to "my app name", :root %>
Ruby language scholars might have spotted the problem without the error message, but once I got it, it was pretty simple. link_to can't be used with a symbol, so that's an easy fix. Alakazam!

<%=link_to "my app name", "/" %>

So all is well now in the land of Heroku. A few things I'm wondering now... When will heroku support newer versions of rails? Is heroku(or will it become) a popular enough deployment option to force package developers to support a heroku friendly version? Will merb make both of these questions moot?

Thursday, December 11, 2008

Get 'em you two!

Rails Internationalization- 1.8 vs. 1.9

I had the chance to demo a rails app at Dev House Boston on Sunday, and one of the questions I got was about making ruby1.8 speak Japanese. I remember this being a big deal for me at one point. There is so much talk of the internationalization in ruby1.9 that when I started my project, I used 1.9 for some of the string processing that I was doing.

When it came time to hook that code into an application, the obvious answer seemed to be sticking with 1.9. However, things didn't look as rosy when I found myself in dependency hell trying to make ruby 1.9 friends with rails, mysql, etc. etc. After applying patches, editing gems (manually), fighting with how gems and debian both want to rule package management (and reading a really long argument between debian developers about the topic, with no resolution), I finally got everything working (sort of). It still had a few hiccups that I didn't know how to deal with (which looked like they could expand into bigger issues), and at this point I was pretty much through trying to fix anything else. So I decided to switch back to ruby 1.8.

It's actually a lot easier than I thought it would be.

The database needs two modifications:
CREATE_DATABASE my_web_two_zero_development DEFAULT CHARSET utf8;

and

development:
adapter: mysql
database: example_development
encoding: utf8
username: root
password:


The global $KCODE should be changed in environment.rb to either "UTF-8" or it's short version like so:

$KCODE = 'u'

Concerning the string manipulation itself,
ActiveSupport::Multibyte::Handlers::UTF8Handler has provided a solution with (string).chars.methods_of_death_such_as_length_index_etc.

But because my goal wasn't full on i18n, but rather just Japanese support, I found that a simple require 'jcode' in my enviroment.rb file gave me what I was looking for, providing methods like (string).jlength. Either one gets the job done when it comes to Japanese. It might be prudent to do some benchmarking or code delving to see if one is better than the other, but for my purposes, I found either to work fine.

I guess there are two things that I took away from this. First, I'm not sure why i18n was so hyped up for 1.9. I guess it was something for people to talk about, but it did obscure the fact that there are multiple simple solutions that will already solve a good deal of the issues in 1.8, but just maybe not as elegantly. Second, adding Japanese support for an app backed with 1.8 seemed impossible, until I tried it. So if my solution ends up being a too messy, as was the case with 1.9, it's probably time to reevaluate what I think is impossible.

Wednesday, December 10, 2008

I love my ninja gmail theme

A Ninja courting a geisha. Fantastic. And the scene changes several times a day. As if I didn't already check my email enough, now I have to check up on a minimalist soap opera under my inbox too.

Tuesday, December 9, 2008

First Post

Hey. It's the classic first post where I promise imaginary readers that I will write every day. Stay tuned for posts months from now when I confess to the same imaginary readers that I haven't been keeping up with my blog.