Wednesday, April 23, 2008

Observatory: Fear

The only thing we truly fear is the unknown.

We are afraid of snakes and spiders because we don't know if they are going to strike.

We are afraid of heights because we don't know if we are going to fall.

We are afraid of strangers because we don't know if they have bad intentions.

If we take the time to learn about the thing we fear, we will find that we are no longer afraid.

It is only then that we can make responsible decisions.

Thursday, November 29, 2007

Tip: Bug in Ruby 1.8.5 on 10.5 Leopard

When I first got Mac OS X 10.5 Leopard, one of the first things I had to do with compile and install ruby 1.8.5 in order to facilitate my job as a Ruby on Rails developer (as we are just getting around to upgrading our thousands of lines of enterprise code to work in rails 1.2.x).

I downloaded, compiled, and installed, ruby 1.8.5 p114, and for the most part things went smoothly.

However I would intermittently get the weirdest error:

NoMemoryError (negative allocation size (or too big))

I still don't know what the root cause of this error is, but as of this morning it seems that downgrading to p52 fixed my problem.

Hopefully this will pan out in the long run, but so far this error (which I'd see several times an hour during active development) has disappeared.

Tuesday, November 20, 2007

Rant: Auto-Refresh News Sites

I was reading and article at www.computerweekly.com this morning, who, like many other news sites, seems to think that they need to force a server side refresh on the whole page every five minutes to reload an article so that I can have the latest, greatest, news in some ticker.

In this case the problem was that their server is flaky, and on refresh, it gave me a "Server Too Busy" error! So now instead of getting to read the article (which was apparently in necessity of updating because the content of individual articles changes so frequently), I get to stare at an error message generated by a Microsoft Web Server.

This is just the most infuriating case in a string of annoyances with auto-refreshing news pages.

One thing I consistently find annoying is how Google News has to refresh the news listing on me, while I'm browsing through the article summaries.

Indeed, it always seems to do it when I am about to click on the link to an article I think would be very interesting to read, and it always seems that that article has rolled off the bottom of the list and I have to dig around if I want to read it!

Now the question on my mind is "why"? Why do we need to have our news updated so frequently (or at all)? Did so many important things happen in the course of the ten minutes I was reading the site that I need to have it updated?

And if I'm that addicted to news, what am I going to do for the hours that I'm actually working? Or for that matter, how do I possibly think I could make it through a nights sleep!

Or is it that they think we are so freakin' lazy that we can't hit 'refresh' several hours later to reload the page if we want to be ten extra minutes up to date with the cutting edge news?

Wednesday, October 31, 2007

How To: Manage Your Own Subversion Repository In Leopard

Mac OS X 10.5 Leopard ships with Subversion 1.4.4 pre-installed. It also ships with Apache2 pre-installed. It does not, however, ship with a pre-installed subversion repository configuration.

So let's say you want to create your own subversion repository host on your Leopard box your own source code management goodness?

You could go to the subversion homepage and download the free svn book and sort through the instructions trying to figure out how they apply to you... Or you could follow these simple directions which I've laid out for you.

Make a Repository

The first thing you need to do is to make a repository. Actually, for my needs, I had to make multiple repositories, so these instructions will set everything up to make that work. It really only changes two steps anyway, so it isn't a big deal.

Now I decided to make my repository collection root directory be in /Users/Shared/, but you can really make it be anything you want, including the ever popular /usr/local. Just be sure to replace /Users/Shared/ with your directory of choice whenever necessary.

Anyway, I opened Terminal and entered the following commands:

$ sudo mkdir /Users/Shared/svn
$ sudo mkdir /Users/Shared/svn/reposname
$ sudo svnadmin create /Users/Shared/svn/reposname
$ sudo chown -R www:www /Users/Shared/svn/reposname

Note that you can create multiple repositories by following these directions but replacing every instance of reposname with the name of the repository you want to use. Thus, if you have multiple repositories, you will have multiple directoris in /Users/Shared/svn

Make Access

Most directions do this later, but I'm going to do it now because I think you are smarter than that.

You might want to create a passowrd file, unless you want full public access to your repository. For our purposes, simple http basic authentication is fine, but remember that the password is only weakly encoded and the traffic isn't encoded at all, so a snooper could get to the information if you access your computer outside of your own computer.

So if you do want to use authentication, create the password using the following command, substituting username for a user name of your choice, and following the directions for password creation:

$ sudo htpasswd -cm /etc/apache2/svn-auth-file username

To add other users to the file, just ditch the c switch in the -cm options to htpasswd. The c stood for create, and since the file has been created you don't want it anymore.

Note that you can put the svn-auth-file anywhere you want, but this seemed like a good place for it in my mind. (Just remember where you hid it from yourself if you put it anywhere else.

Apache Configuration

Navigate to /etc/apache2/other and use your favorite command line text editor as root to make a file named anything you want (I chose svn.conf, but you could name it foobar_banana.conf and it would still work!):

$ cd /etc/apache2/other
$ sudo vim svn.conf

Now that you are editing this file as root, you want to make it contain the following bits, and save:

LoadModule dav_svn_module /usr/libexec/apache2/mod_dav_svn.so

<Location /svn>
    DAV svn
    
    SVNParentPath /Users/Shared/svn
    
    AuthType Basic
    AuthName "Subversion repository"
    AuthUserFile /etc/apache2/svn-auth-file
    Require valid-user
</Location>

Note that you can leave off all the authentication related stuff if you didn't want authentication on your repository. Also note that you need to fix the SVNParentPath and the AuthUserFile if you varied from my directions.

Restart Apache

Now restart Apache. This can be done in the Sharing panel of the System Preferences application. Just click to turn off, and then back on, Web Sharing.

Now, if you didn't make a mistake, you should be ready! Try going to http://localhost/svn/reposname (where you need to put the repository name you chose earlier instead of reposname!) and see what happens.

If you are lucky you'll see revision 0 of your repository. But most people are human and will have made a typo that results in an error. For hints on what created the error, trying checking out /var/log/system.log and /var/log/apache2/error_log for hints as to what you did wrong. (And as a bonus, the Console application works great for monitoring thes logs as they are writen to!)

Where From Here?

And now you are ready to use your repository. At this point I figure you already know how to use SVN and don't need my help anymore. But if you need to know how to use SVN, just refer to their book, which tells you everything you need to know, including how to make your server better!

EDIT (11/6/07): Forgot to encode my character entities in the example script source. I fixed this so that the <Location> tag actually shows now.

EDIT (04/23/08): The chown line now uses the full path as it should. Thanks to all those who pointed this confusion inducing mistake out.

Sunday, October 28, 2007

Tip: Leopard and Legacy Rails

Due to the size and requirements of our enterprise healthcare application that we've written on Rails, we've been sort of stuck at rails 1.1.6 and ruby 1.8.5. Not that we don't want to upgrade, but in trying to build on functionality so we can make enough sales to sustain ourselves, we've had to forgo tracking down all the problems that keep us from going to rails 1.2.3 and ruby 1.8.6

As a good Mac geek, I upgraded my computer to Mac OS X 10.5 Leopard this weekend, deciding to use the archive & install feature because I had some issues upgrading from 10.3 to 10.4. (my compilation of ruby 1.8.4 would crash randomly). Of course, Leopard, being all cool and stuff, ships with rails 1.2.3 and ruby 1.8.6.

Fortunately, compiling ruby 1.8.5 was straight forward (just don't use the --enable-pthread option or you'll get a crash!), and otherwise the instructions to install gems, postgres, and RMagick all worked exactly the same as on Leopard.

And since Apple manages the ruby/rails installation that ships with Leopard via a Ruby framework and some symbolic links in /usr, it means that if you compile and install everything into /usr/local, you can easily revert back to Leopard's ruby/rails whenever you want.

So the net result: If you have a legacy app, just compile and install and you are good to go.

Speaking of, I really should make a set of blog articles that goes over the compile/install procedures for ruby, rails, postgres, and RMagick, on Leopard. But right now I'm having too much fun playing with Time Machine to care. :)

Edit (10/28/07): As noted in this article, rails 1.8.5 p114 has a bug in it. However it appears that p52 works just fine.

Tuesday, October 23, 2007

Video: Keep It Simple Stupid!

Being that I'm a simple-is-sexy kind of person, I've always been flabbergasted by the busy packaging so many corporate marketing teams put out.

As a developer, I've learned that the KISS principle (Keep It Simple Stupid) is very important for solving problems. And as a teacher I've experienced the confusion an onslaught of information can provide. Indeed, in most situations, whether it being a scientist, and engineer, a teacher, or even a parent, keeping it simple is important.

Which is why I loved the following video. It does such a good job of punctuating the differences between Apple's approach of simplicity, against the corporate world's attempts to attract attention while cramming the package with information.

Of course the ironic thing is that, with all these super-busy boxes on the shelves, the one that actually stands-out is the simple-sexy one.

Rant: Rails Lacks Accessor Bottlenecks

Being a longtime user of (and zealot for) Ruby, I have a made a name around the office for my unusually strong understanding of its details. Thus my employers decided that, out of our team of developers, I should be the one to write the security sub-layer for our Ruby on Rails based chiropractic applications (as it would require digging into, and understanding the internals of Rails.

Now before I proceed to beat Rails around a littl bit, I don't want you to get me wrong. I love using Ruby on Rails and would easily chooose to do this project (and future projects) in it again, but sometimes I find some of their design decisions to be, well, web-developerish, while we need a more robust enterprise-developerish solution.

A Bottle With Too Many Openings Can't Hold Water

One of the design patterns that I have seen over and over again in Object Oriented APIs is the use of bottle-necking. That is to say, even within your own class, you choose to use a set of accessors to get at instance variables instead of poking at them directly.

The big benefits to this approach are two fold: It allows you to be more agile with changes (as you only have edit the accessors to change behavior), and it allows third part developers to easily augment or override the default behavior of your code.

An simple example of this may be a simple vector class that stores a magnitude and an angle. Now this angle, in all reality, needs to be between 0 and 360 degrees. So if you have two ways to set this data (from rectangular or polar coordinates), you would have to enforce these limits, probably by using a modulus operator. (Which isn't very DRY, now is it?) But what happens when you have to change the behavior? Maybe the angle needs to be stored in radians, maybe the range needs to be changed to -90 to 90, or maybe it needs to be compass oriented instead of right-handed-axis oriented? Or maybe you just want to add a way to set the angle without changing the magnitude?

All of these requires refactoring your code, which requires duplicating and/or altering your code in several locations! But if you were to make a single accessor for getting, and a single accessor for setting the internal value, then all your other code could go through this accessor (including possible intermediate accessors) to enable fast, agile, and DRY code changes!

Playing With Steam Engines

So, now, let's imagine your employer gives you the spec that your enterprise Rails driven software must have a security system where you can restrict read and write ability to different models, on a per attribute basis. This is what I faced over a year ago.

The way I really wanted to solve this was to override the accessors to the basic hash that stores, as key/value pairs, all the data for the table row the objects represents. That way I could add my own code that would allow or deny access at this fundamental level.

Unfortunately this basic and simple idea (based on past experience with other APIs) exploded in my face. You see, the @attributes hash instance variable that ActiveRecord uses to store these key/value pairs is directly poked and prodded by many separate methods throughout the ActiveRecord class. Thus I had to override all of these methods, making them call the same friggin security check method, to decide if they could continue onto their default implementation or if I should restrict access. (I'm only lucky that the runtime generated accessors utilized standard accessors, or else I'd be re-writing the code-generation routines as well.)

Of course, all this work meant that besides sinking a lot of the company's time and money into implementing a task that should have been simple, maintaining our release against newer versions of Rails is more costly because of all the hacks I've had to do to meet the requirements.

Which is why I'm so peeved at their code. If only they had followed good design practices and bottle-necked all calls to @attributes through a read and write accessor method, it would have been easy to implement customized behavior at this point in the program flow, and thus would have made my security requirements a trivial task.