Wednesday, January 21, 2009

PHP : Getting a PHTML download dialog box on Linux?

Blogging this mostly for notes, as it was a stupid simple solution but no amount of googling gave me what I needed:

You’re setting up a LAMP server, probably on Ubuntu though I suppose it could happen on Windows.  You’re getting this annoying error, when you try to hit your index.php page, that asks you to download or open the PHTML file.   You do some researching, say “Ah, heck, I forgot to apt-get install php5” or libapache2-mod-php5 or whatever, and you get those and you restart apache, but no matter how many times you bang your head against the wall, it doesn’t go away.  Worse!  You create a brand new php file, and that sumbitch works.  But your existing code doesn’t.

With me?  Had that problem?

Yeah, clear your browser cache.  You’ve fixed the problem, and your browser is still serving up the old, broken bits.

 

You’re welcome. :)   [Credit to coworker Jesse for finally finding the solution…]

Tuesday, January 20, 2009

CentOS Installation Help : Rails OpenSSL-dev Zlib-dev etc…

This might not be a universal rule, but thus far it seems to hold true for me.  When installing development libraries on an Ubuntu/Debian machine, you tend to use “dev”, as in “sudo apt-get zlib-dev”.  When you are on a Centos/Redhat (RPM) machine, you tend to use “devel” as in “yum install zlib-devel”.

This caused me no small amount of annoyance as I was installing Rails on CentOS today, getting all sorts of zlib and openssl errors, and whenever I did a”yum install zlib-dev” it would just say “Nothing to do”, which stupid me was taking to mean “This library is already installed.”

No, apparently it means “That’s not the name of a package I recognize.”  When I did “yum install zlib-devel” it came right up and solved all my problems.

[Off-topic?] Where Were You?

Today, as you may have noticed, is a pretty big day here in the United States.  It’s a day that many people thought would never come, at least not in their lifetimes.  It’s a day that I remember hearing about in school as a sort of “Maybe one day…” thing, something in the future, not the present.  I’m speaking, of course, about the swearing in of our first Hawaiian president.

As I tried to explain to my 6yr old this morning, “There are times in your life when people will ask ‘Where were you?’  Where were you when we landed on the moon, where were you when 9/11 happened?”

“I wasn’t alive for either of those things, Daddy.”

“I know, sweetie.  But you know what?  Years from now, when you’re Daddy’s age and you have kids your age, people are going to ask you Where were you when they swore in the first Hawaiian president.”

So, I’m asking all my readers, on all my blogs:  Where were you?

Me, personally, I’m at work.  My kids are at their grandmother’s house, because the power went out at about 6:30am.  Which stinks, because there’s pretty much no way I will be able to DVR the ceremonies on television if I have no television :).  But I will be watching on line as best I can.

Where are you?

How optimistic are you about our new president, as far as technology goes?  We’re talking about a man who fights with the Secret Service over whether he has to give up his Blackberry, whose weekly speeches go out on YouTube, who has had the Change.Gov website up since pretty much the day he got elected.  A site, mind you, that actively solicits input from the people, and doesn’t just make a bunch of bland statements buried in documents 1000 pages deep just because the rules say they have to.  Are you optimistic for our lives as geeks?  Or pessimistic that he can’t live up to the hype?

Friday, January 16, 2009

The Evolution of Brand

photo  I thought this was funny.  Pepsi’s high caffeine product, Max, was originally introduced only in diet form – Diet Pepsi Max.  Recently it appears that they’ve dropped the “diet”, just calling it Pepsi Max – but it clearly says “0 Calorie soda” right on the side.

Right away, this confused people.  The office admin who filled our refrigerator today, when told this, said, “Wait…so that’s diet?  I totally didn’t mean to get that, we already have too much diet soda on the list, I have to get more regular for the people who don’t drink that stuff.”

A coworker in the next cube chimed in with, “You’re right, I saw that and wouldn’t touch it.”

But…look closely at the box.  That can came from that box, I did not set that up. The box still stays Diet Pepsi Max, while the can does not.  So literally we hit it at exactly the point in time where you could say “The machine that makes the cans has been updated with the new graphics, but the machine that makes the boxes has not.”

It also looks like they’ve gone more black in the coloring, and possibly got rid of (or at least downplay) the ginseng.  They changed the swooshy logo, and went with lowercase on the “pepsi”.  All subtle things, until you look at them next to each other.

Flight 1549 : Ummm….found a bug

http://flightaware.com/live/flight/USA1549

While Googling for news on Flight 1549 which went down this afternoon (apparently everyone is fine and no terrorism is suspected), I first found FlightAware.com linked above.  Note some of the…ummm…uncomfortable parts of the UI?

* Duration of flight:  6 minutes

* Status:  Arrived over an hour ago!  (I assume this is dynamically updating so your mileage may vary)

* In the upper right corner it clearly says, “News: Flight 1549 Crashes Into Hudson River.”

I worked at TripAdvisor, a hotel booking site, when New Orleans flooded.  It was crucial to us, a production bug, to get hotels out of the database that, you know, weren’t in business anymore.  It seems that perhaps somebody at FlightAware needs a similar job.  “Arrived” ends up looking pretty tacky.

Thursday, January 15, 2009

Rails : Internationalizing Views

I’m not an expert in i18n, but there seem to be two somewhat separate strategies for how to tackle the issue of translating your content into different languages.  First is the idea of externalizing your strings.  So for example say you have this content:

<h1>Welcome to the home page!</h1>

Well what you do is name it:

<h1><%= :homepage_welcome %></h1>

And then you define that resource someplace that it can be swapped out dynamically.  Rails 2.2.2 has some great support for this (I am using the karmi demo if you want to follow along), then in config/locales you can have a file en.yml (for English):

en:
  homepage_welcome:  “Welcome to the home page!”

and fr.yml (for French):

fr:
  homepage_welcome: “Bienvenue à la page d'accueil!”

Back in your code you invoke the translator:

<h1><%= t(:homepage_welcome) %></h1>

And with a little I18N magic (again, see Karmi for what’s really going on), you have multi language support.

 

Well, the problem with this is that on content of a meaningful size you’re going to start running into trouble breaking it into named pieces.  You’re either going to break it into such small pieces that you lose the context in which it was used, or else you name it too generically and your translators no longer give you the optimal translation because you’re using the word in different ways, or you just plain have to translate pages full of content all at the same time.  Worse, what happens if you’ve got graphics that need to change with the translation?  How do you externalize that?  I’ve got an icon that says “New!” in a little star shape, how do I use I18N to translate *that*?

Here’s something I’m experimenting with to do the entire view pretty quick.  I haven’t gotten enough feedback yet for whether it’s a good idea, but hey.

You’ve got a controller, home, and an action, index.  As we all know, Rails will then make some assumptions that at the end of method index, it’ll render the file in app/views/home/index.rhtml (or .html.erb if you want to do it the new way).  Well, I thought, maybe that’s a good place to sneak in my locales?

So I created app/views/home/en and app/views/home/fr and copied index.rhtml to both these directories.  In the fr/ version, you make any and all changes you have to make – including changing image paths, etc…  Change it right there in the code.

Then, back in the controller, we do this:

def index
   …
   render :action=>”#{current_locale}/index”
end

And you know what?  It actually worked.  I swapped out my locale to French and I get my fr/ page instead.

THIS IS VERY BASIC.  Among other things, you’d want to make sure that the content exists for the locale you’re looking at, and have some default to fall back on.  The t() method described above actually does this, allowing you to say stuff like this:   t(:homepage_welcome, :default=>”Welcome to the homepage”). 

Also, this implies that whoever is doing your translation is going to be comfortable getting raw HTML pages.  That’s not ideal.  You really do, if possible, want to separate out the content.

Lastly, you’re repeating yourself.  That’s not great.  So before tackling this you should do your best to get the logic out of the page (and into the controller), and really only use this technique on pages that are almost entirely content.

Like I said, I’m still working on it.  Maybe I’ve got enough Rails traffic on this blog that I can get some discussion going about how to improve the strategy.

Zebra Debugging

You know the old saying, when you hear hoofbeats think horses, not zebras.  This is an example of almost that, but not quite.  I’d rather call it zebra debugging than call myself an idiot. :)

Context: We have Verizon FIOS in the house, with the DVR sharing option.  This means that there is a box in the living room that does all the recording, and a television upstairs where we can either watch live tv directly, or else watch recorded programs streamed from that box.  In the morning, my wife and I record the news that starts at 5am so we can fast forward through the commercials and just see the important bits while getting ready for the day.

Well this morning we woke up to a “Currently unavailable” message.  Hmmm, maybe that’s what happens in FIOS land when the “cable” is out.  Weather problems?  Nope, no snow yet, although there is supposed to be a little bit.

I try putting on the channel 7 news directly.  Nope – unavailable.  I bring up the DVR function (which refused to give me the news 2 minutes ago) and call up something that was recorded last night.  Works fine.  So I’ve learned that the box is in fact connected to the network and can get content.  Check.

I call support, to see if there is an outage.  I realize after a moment that Verizon has got an entirely automated system – the thing is going to walk me through rebooting boxes and all kinds of different things, which is actually fairly impressive, technologically.  It said, “State your problem”, I said, “Currently unavailable.”  It said, “Ok, you’re saying that one or more of your televisions is currently showing a Currently Unavailable screen, is that right?” and then walked me through detailed questions – all televisions?  all channels?  Good questions, and I had to say “Not sure”, because I wasn’t.  Hadn’t checked yet.

It then goes through some basic steps which were so painfully basic I had to give up on them. When I realized it was asking me slowly…very slowly….whether the television was actually turned on, I said “Operator” and started waiting in line for a human :).  I’m not kidding, it really did say things like “Walk over to the box.  Now, when you are there, say Next Step.  Or say, Repeat that instruction” and “Once you are at the box, look for the yellow power light.  If you do not see it, press the power button.  Say Next Step when you are done…”

Anyway, back to the timeline.  The automated system did reboot the boxes for me. Still nothing.

So I go downstairs and check the base station, the one that does the recording.  Works fine, and comes up on some Blues Clues or something (Nick Jr, maybe?) that it was recording for the kids.  I check the kids room, and their tv also comes up fine on Sprout, the channel they live for.  So it’s localized to just the television upstairs, that’s weird.

So now I’m on hold, trying to figure this thing out myself.  Something about this specific box.  I cold boot the box by yanking the power cord….nothing.  I run through the checklist in my head – box works because it brings up guides and menus and all the usual things, it gets content that was previously recorded.  I also note that my phone and internet have not gone out.  So literally the problem is that this box is not receiving a live television signal.

It dawns on me that I’ve been messing with the router.  I have two in the house, the FIOS one and my original internal network.  Because of problems with some machines I had started recently using them to back each other up wirelessly, so some of my machines are connected directly to the FIOS router.  Could there be an IP clash?  I start checking the System Info on the cable boxes and comparing it to the config information on my laptop….netbook….iPhone.  Looks like there might be, there seems to be no clear designation where this router serves up wireless addresses in the 100+ block or some such like other routers do.

At this point the rep comes on the phone and tells me, ready for this?  “It’s a local outage.  Just local channels.”

Pause.

Oh.

My upstairs television was tuned to channel 7, a local channel.  When I rebooted it, it came back up on channel 2, a local channel.  My two televisions downstairs were both on cable channels, and after seeing a live signal I never thought to try different channels.  I put my upstairs television on the Sprout channel.  Works fine.

I say, “You know, given that you have my phone number and address, perhaps an automated message right up front would have saved me all this time?”

“Yes, sir,” she responds, “We did just update that message.”

“So you’re telling me that if I’d called 10 minutes later I would have known this and not have had to sit and wait for you to tell me?”

“Sorry about that.”

Thursday, January 08, 2009

There Can Be Only One…..Database.

Ok, here’s the premise.  You build web apps for a living.  In general, a web app needs a database.  But should it ever have or need more than one?

You’ve got one web app, Primary, that uses PrimaryDB.  PrimaryDB has tables First, Second, … and so on, up to let’s say Tenth.  With me?

You also have a web app, Secondary, using SecondaryDB with tables Blue, Green and Red.  Yes I deliberately switched conventions to make it a little easier to understand.

So, new project comes along, and it turns out that Secondary needs access to tables First through Ninth.

What do you do?  Some options:

* Copy the tables from PrimaryDB to SecondaryDB and maintain two copies.

* If your database supports it, create “synonyms” on Secondary for the Primary tables.

* Configure the Secondary application to enable access to both PrimaryDB and SecondaryDB.

* Split First through Ninth into a new database, CommonDB, and put CommonService in front of it.  Tell Primary and Secondary that this is the new way to access that resource.  (In a pinch this can also be simulated by putting a special page/interface inside of Primary that exposes just those parts of PrimaryDB to be shared, and let Secondary hit that as a web service.  Not optimal, as  you can’t independently scale that service based on need, but if you had limited operational resources for bringing up new production servers you could go that way.)

 

Thoughts?  At one time or another I’ve done all of the above. I’m a fan of the last one, if you can reasonably assume that this is not the last time you’ll be asked to do this.  Maybe instead of nine tables it’s 90 tables, and maybe instead of just Secondary needing access to the data, you can envision Tertiary and Quarternary and a whole bunch more apps to come, all of which are going to need access to those tables as well?

[Since technology matters, I’ll point out that the database in question here is MySQL. The actual technology for the webapps now is PHP, although for the solution we’d be open to Rails or .Net as well.]