Archive for September, 2006


Rails iCalendar improvement

Saturday, September 30th, 2006

I came across this thread that simplifies the ical controller from my previous example. It correctly sets the content type header and removes the need for a template. The new version is:

class IcalController < ApplicationController

caches_page :competitions

def competitions headers[’Content-Type’] = “text/calendar”

cal = Icalendar::Calendar.new

Competition.find_all.each do |comp|
  event = Icalendar::Event.new
  event.start = comp.date
  event.end = comp.date
  event.summary = comp.name

  cal.add event
end

render_without_layout :text => cal.to_ical

end

I hadn’t used the render_without_layout command before, but it’s very handy for situations like this.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Rails iCalendar improvement digg.com digg it!  |  reddit reddit!

Getters and Setters

Friday, September 29th, 2006

I was chatting to Simon the other day and the question of, should you have getters and setters in your Ruby classes, or should you just let other classes access the attributes directly, came up. We were talking about ActiveRecord, which dynamically creates them for any columns in the table the class is representing.

The short answer is, if you want other classes to access that data, yes, you need getters and/or setters, but for different reasons that you might think if you come from a Java world. Getters and setters are one of my pet peeves in Java. I hate it when I see them thrown in by default for every field in the class, reducing it to nothing more than a C struct.

The good reason for not allowing direct access to a field in Java is data encapsulation. By making it private you can decide if it’s read-only or read/write (or neither). But I think this is a poor reason, in so much that other objects shouldn’t be pulling data out, but asking it to do things. Rather than starting from a view point of what data does this class provide, you should think of what are its responsibilities.

But that is tangential to what I want to talk about, why are getters and setters so prevalent in Java? I think the first reason is the early OR mapping frameworks. They typically required you to inherit from a class, or broke OO (no inheritance in EJBs?!?), so you treated the domain object as struct, just to ferry data from Java to the database. Then you’d put logic in other objects and you’re just doing procedural programming. I think the situation is better now that you can work with POJOs (e.g. Hibernate) but you still see tutorials following the old pattern.

The second reason is the madness that is field access in Java. Getters and setters can protect you from this. Java binds field access at compile time, i.e. to a variable’s static type, e.g.:

public class A {
    int num = 0;
}

public class B extends A {
    int num = 2;
}

public class Test {
    public static void main(String[] args) throws Exception {
        A a = new B();
        System.out.println(a.num);

        B b = new B();
        System.out.println(b.num);
    }
}

Would output:

0
2

when you’d hope it would do something sensible like:

2
2

i.e. you shadow fields rather than override them, so you can get weird bugs if the static type is different from the runtime type. The variables can even be different types! Methods are determined by your runtime type so we can make sure we’re always accessing the right variable, e.g.:

public class A {
    int num = 0;

    public int getNum() { return this.num; }
}

public class B extends A {
    int num = 2;

    public int getNum() { return this.num; }
}

public class Test {
    public static void main(String[] args) throws Exception {
        A a = new B();
        System.out.println(a.getNum());

        B b = new B();
        System.out.println(b.getNum());
    }
}

Does output:

2
2

so unless the field is defined in your class, you really shouldn’t access it directly. This means to be safe, all fields should be private and we need protected scope getters and setters if we want that field available for subclasses, what a pain, but helps explain why they are so prevalent.

Back to Ruby, how does it deal with this? If you look back at the top I said if you want to access the data you need getters and setters. This is because attributes (Ruby’s name for fields) are private to an object, and everything you ask from an object has to be a method, basically you couldn’t get to that attribute directly if you wanted to! Ruby also doesn’t have the problem of field shadowing because you don’t declare variables, so when you reference it, you’re referencing the only variable with that name.

So what do the getters and setters look like?

class Test 
    def someField
        @someField
    end

    def someField=(newValue)
        @someField = newValue
    end
end

aObject  = Test.new
test.someField = "blah"
test.someField >> "blah"

i.e. our getters and setters look like we’re accessing a field directly but they are actually method calls. Without these, if we tried to access a field, Ruby would complain that no such method exists.

Since this is such a common pattern Ruby has some shortcuts:

read-only:

class Test
    attr_reader :someField
end

write only:

class Test
    attr_writer :someField
end

read/write:

class Test
    attr_accessor :someField
end

All these methods can take multiple arguments if you’re defining multiple fields.

A good summary of all this can be found here:

http://www.rubycentral.com/book/tut_classes.html#S2

But Ruby’s not perfect. A subclass can access attributes from its parent. which means you’re dependant on its implementation, but a code review can stop that.

The bigger problem is clashes with mixins. If a mixin uses an instance variable you can get collisions. A mixin has no state, that instance variable it refers to belongs to the object that included the mixin, so if it uses a variable with the same name you can get some weird behaviour. Because there is no static typing, the object’s methods and the mixin’s method can change what is held in that attribute and you won’t see that error until runtime where you’ll probably see a missing method error. Typical workarounds are prefixing variables with some sort of namespace to avoid collisions, or using a module level hash to store the mixin’s state outside of the object.

All in all I prefer the Ruby way of getters and setters. On the surface it looks the same but by preventing direct access to attributes and using virtual attributes (not covered here), you classes are less likely to become structs and more like genuine objects.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Getters and Setters digg.com digg it!  |  reddit reddit!

My lap is safe for now…

Friday, September 29th, 2006

I noticed a while ago that an IBM Thinkpad finally caught fire. IBM (Lenovo really) has issued a recall for some batteries. Thankfully my trusty T30 is not on the list. It’s only Sony batteries that are affected, and my one is made by Sanyo, so I’m safe for now.

But if it’s overheating that’s causing these fires it won’t be long before my hard disk or power adapter bursts into flames…

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit My lap is safe for now… digg.com digg it!  |  reddit reddit!

Weird Hibernation Issues

Wednesday, September 20th, 2006

No, nothing to do with sleeping for a very long time, but weird things my Thinkpad does when it hibernates. For the most part hiberation works very well on my Thinkpad. I use the hardware supported one rather than the one built into Linux, but it does do a couple of odd things.

The first is that Firefox occassionaly (but not always!) dies during hibernation. I think I’ve narrowed it does to either Ajax apps running (some network connection getting killed, then killing the app?) or I’m using swap (more likely Firefox has been opened long enough that something else is the cause). It’s not really a problem because I use Tab Mix Plus, which can restore my session after a crash, but it is frustrating if you open a bunch of articles that you want to read on say a long train journey, only to find the browser is gone!

The other weird issue is that my fonts disappear from OpenOffice and Microsoft Office (running via Crossover Office after hiberation. This includes menu fonts and the fonts used in the document. All the spacing remains correct, just no text. It only happens to these two programs, everything else is fine. Restarting xfs doesn’t make a difference, the only way to fix it is to restart X. This problem is just bizarre.

If any one has any solutions to these problems, I’d love to hear them!

Update 1: It looks like the hibernation processes shuts down the network connection and all programs that depend on it. I don’t know if that’s a Gentoo specific thing. The only other process that isn’t running when the computer is turned back on is gconfd-2, but unfortunately starting it up doesn’t help with the font problem.

Update 2: The gconfd-2 thing was a red herring, it was started up by Firefox. Killing it doesn’t affect the fonts. I guess something in X is dying, which can only be fixed with a restart.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Weird Hibernation Issues digg.com digg it!  |  reddit reddit!

Upgrading a Rails app

Wednesday, September 20th, 2006

Now that I have some free time I can work on my golf league Rails app. There’s a bunch of stuff I want to do:

  • Upgrade to Rails 1.1
  • Upgrade to the stable release of Typo (4.0.x)
  • Start using Capistrano for deployment
  • Add in some tests

Typo

Last time round I started using Typo to manage news and photos (via Flickr). The problem was that I was using a trunk version (r933), which had some stability issues to say the least, but did the job. The biggest problem was a memory leak that caused DreamHost to kill it off whenever it got some significant load. A lot of these issues have been fixed in the current stable release (4.0.x), and it also uses Rails 1.1, so that’s a good excuse to upgrade (although unnessary for the other bit because it’s a separate app).

One thing I always wanted to do was integrate the admin screens of the league manager as tabs in Typo’s admin pages. I think this is being talked about for 4.1 but isn’t available now. So that doesn’t leave much space for tighter integration, and I don’t like having to maintain two code trees. Typo is also overkill for the odd monthly announcement.

Another thing I’ve considered is using a simpler CMS, e.g. Radiant. I haven’t looked at it much, but it supports something called behaviours, which allows you to do something different on a particular page. That could replace the standalone app that handles leaderboards, forms, etc. Another alternative is to just write a simple news posting system, then I wouldn’t have to worry about merging code bases, user models and all the authentication headaches.

If anyone else has experience in running two Rails apps as part of one web app, I’d love to hear about it.

Rails 1.1

I only just upgraded to 1.0 the last time round. It would be nice to see what the current state of the art is. The main problem here is that my copy of Agile Web Development with Rails only covers Rails 1.0, all my info on Rails 1.1 is a bunch of blog clippings.

What I’d prefer to focus on is the performance and memory enhancements I’ve been reading about on RailsExpress.blog. Rails on DreamHost is slow, and if you consume too much memory, your app gets killed. It’d be nice to sort this stuff out, especially since my users aren’t all technical.

Capistrano

Another pain with Rails is that almost certainly, deploying the thing that works on my laptop onto DreamHost won’t work. I don’t know much about Capistrano, but I’ve heard it takes away deployment pain, so I want to give it a go.

Testing

Being a hobby app there are no tests. Most of the logic is just editing records so I don’t need tests, but there are some tricky scoring and ranking things that should be verified with test cases. After that there’s ZenTest. It’s an automated tester that makes sure everything is still working with each change. It’s a different style of development that I’d like to try, it sounds a lot more helpful than occassionaly doing an ‘ant test’ that takes several minutes to run. ;)

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit Upgrading a Rails app digg.com digg it!  |  reddit reddit!

When did PayPal get so slow?

Wednesday, September 20th, 2006

When did paying for things by PayPal get so slow? I recently bought a couple of things off eBay and paid via PayPal. For days after I kept getting these payment reminder emails from eBay, but the website showed the payment as made. On closer inspection PayPal had marked the payment as pending. It seems now rather than doing an instant transfer PayPal uses something called echeque that takes 7-9 business days, that’s almost two weeks! It now takes twice as long as it does to write a real cheque, post it and clear into the seller’s bank account!

What’s really frustrating is that PayPal kept recommended to use a bank account rather than a credit card, or better yet keep money with them. But did they use the funds sitting in my PayPal account first? No. I assume credit card payments can’t be as slow, so I’ll be using them with PayPal in future, or better yet, another payment provider altogether.

Update: It turns out the e-cheque only applies if you don’t have a credit card registered. My credit card had expired, but I didn’t bother updating PayPal because I use my bank account. Once I updated it, the instant transfer option was back.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit When did PayPal get so slow? digg.com digg it!  |  reddit reddit!

End of an Era

Wednesday, September 20th, 2006

Last week marked my last day Runtime Collective (now Magpie). I had worked there for just over four years, and it was my first job after university, so I left with mixed feelings. Sad that I was leaving what I knew behind, but at the same time felt it was the right time to leave. It’s been a good four years, especially watching the company transform from a consultancy to an ISV. I had a great opportunity to work on their Search and Alert product from the get go, which helped me expand my programming beyond just the web and databases.

What made my mind up was when our London office was closed. The main office was always in Brighton, and try as we might, we never got the London operation going, the offices were just too close together. But so it’s not forgotten, I took some pictures of those final days. :)

Just two desks left Empty Office Giles and Sian That's everything Locking up the van Heading to the pub

Thanks to everyone at Magpie (past and present) for the chances they gave me and I wish them all the best in the future.

Spread the word: Technorati related  |  del.icio.us bookmark it!  |  submit End of an Era digg.com digg it!  |  reddit reddit!