Archive for July, 2006

Do the Locomotion

Thursday, July 20th, 2006

Rather than go through the rigmarole of installing Ruby on Rails on the Powerbook I’ve decided to go with Locomotive.

Basically this is a Mac Application Bundle, containing a version of Ruby, an installation of Rails and various other bits and bobs, all underneath a single .app. Start Locomotive, select Terminal and it starts a bash session with all your paths predefined to the ruby/rails installation within the bundle.

All in all, a much simpler installation. I’ve not used it for any serious development so we’ll find out if it lives up to its initial promise.

Baby got back

Thursday, July 20th, 2006

My Powerbook is back from the repair shop. A brand new 5400 RPM drive and a fresh installation of Tiger. Nice. Unfortunately the CD drive still does not work but things feel pretty good. We’re a three Mac household now!

Speedwise the Powerbook feels faster than I remember it (probably down to the faster drive). However, I have noticed a number of beachballs – something that doesn’t happen on our (Intel) Mini.

Gorilla/Guerilla

Saturday, July 15th, 2006

One of the joys of writing about stuff is that you can set yourself pointless tasks like this.

Sql Server – No Limits

Friday, July 14th, 2006

I’ve been playing around with the Ajax Scaffold recently.

Because of the trouble I’ve been having with scrptxfr (meaning that Rails cannot copy my dev database structure to my test database) I’ve been working in MySql and relying on migrations to move over to Sql Server when I’m done.

But I’ve hit a problem. Ajax Scaffold uses pagination all over the shop. Pagination needs to be able to ask for records 20 to 30 out of a particular dataset. This is easy in MySql – just use the limit clause, specifying the record numbers that you want. It’s not easy in Sql Server. Sql Server offers you top so you can grab the first 30 records. But nowhere does it offer you a filter returning record 20 to record 30. So the SqlServerAdapter tries to fake it – it does (select top 10 * from (select top 30 from table order by id desc) order by id asc) – (I may have got my ascs and descs the wrong way round). This works. It’s nasty but it works. Until you use an :include or an :order. Then it just falls over in a crumpled heap. Whimpering.

The only way around it that I can think of is to hack the SqlServerAdapter so that it does a select top 30 * from table, disconnect the recordset (it’s only ADO after all) and then delete the first 20 rows. Not nice eh?

Another ActionWebService annoyance

Monday, July 10th, 2006

It would appear that you cannot have a void method in ActionWebService. If your API looks like this:

api_method :my_procedure, :expects => [{:something => :int}], :returns => []

you will get nil object errors when looking at the WSDL or invocation scaffold.

Instead, you must do this:

api_method :my_procedure, :expects => [{:something => :int}], :returns => [:int]

and return a dummy value at the end of your implementation.

ActionWebService and dates

Friday, July 7th, 2006

As I mentioned before, I have been having a few problems passing dates, date/times and times over ActionWebService.

I’m not too sure where the fault occurs but it seems to manifest itself in ActionWebService/casting.rb. Each field from your model is passed through as a value along with a type identifier. The areas where I am having problems are where that type is :date, :datetime or :time. In each case, casting.rb examines the type parameter and chooses to treat the value as a Date, DateTime or Time object respectively. Sounds sensible no?

But, somewhere along the line the type and the actual object do not match. If you call DateTime.parse(t.to_s) when t.is_a? Time you get an error. The call to parse only works if t.is_a? DateTime. The same applies for Date.parse and Time.parse.

I have amended casting.rb to get around this problem (starting at line 98):

          when :time            value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash)            if value.is_a? Time              return value            else              return Time.parse(value.to_s)            end          when :date            value = "#{value['2']}/#{value['3']}/#{value['1']}" if value.kind_of?(Hash)            if value.is_a? Time              return value            else              return Date.parse(value.to_s)            end          when :datetime            value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash)            if value.is_a? Time              return value            else              DateTime.parse(value.to_s)            end

However, this is just a bandage on the symptom and does not solve the underlying cause. I’m still hunting for that one.

PS: Of course, if you want to deploy your application to a different server you’re as well to freeze Rails into your application’s vendor folder to make sure your amendments aren’t forgotten.

Shocked

Thursday, July 6th, 2006


We all knew that Apple’s user-interface standards were slipping. But this is shocking. A print preview (using the aptly named “Preview”) fails on one of the most important (and psychologically tested) fundamentals of Apple’s UI guidelines. It’s not even like it is hidden away. And it was correct in Panther.

Follow up to "Why you should use Ruby on Rails"

Thursday, July 6th, 2006

They said no.

Mongrel Cluster

Wednesday, July 5th, 2006

I’ve known about Mongrel for a while now, but never really looked into it. However, it appears to have a feature that will work extremely well with RForward. In Cluster mode, Mongrel will spread itself across a number of consecutive ports – which is exactly what RForward likes. I was going to write a WEBrick service installer to run multiple WEBrick processes across the different ports. It appears that the work has been done for me.

However, the instructions are for Linux. When I get the chance I will try them on Windows, but has anyone else had a go yet?

Why you should use Ruby on Rails

Monday, July 3rd, 2006

It’s happened. I’m finally being held to account for using a “non-standard” development tool and I need to justify myself.

So, in preparation, here are my arguments.

In favour of Rails

Active Record
The reason I looked at Rails in the first place. The simplest way of mapping database tables to objects I have found. And the lack of verbose XML configuration files (and Ruby’s dynamic nature) means that getting started takes little time and handling changes is a breeze.

Migrations
By defining your database schema using Migrations you can switch between database environments relatively easily (as long as you are careful about your use of find_by_sql). In my case, many of our smaller clients have difficulty with the idea of buying SQL Server licences on top of our own licence fee. Rails would have made that a non-issue as we could deploy as easily to MySql or PostgreSql.

Testing
Create a model and Rails creates a unit test. Create a controller and Rails creates a functional test. I’ve not looked at integration tests yet but I’m sure I will make heavy use of them soon enough.

ActionWebService
In many ways this is the part of Rails that gives me the most grief. Plus DHH and the other core Rails developers are obviously pursuing REST strategies (like ActiveResource). But, in a .Net and Delphi world (as I am), SOAP services are the simplest way to talk to everyone else. And, of course, it is fully testable.

Ajax
Yes, you easily integrate one of the many AJAX libraries out there into your own code, but Rails makes it nice and easy. And with RJS it’s extremely powerful without actually having to do any Javascript.

Test Fixtures and the entire testing framework
So far, nothing that has been mentioned could not be done by downloading the appropriate libraries for .Net. But that does take some effort. Plus, once you have written your unit tests and your functional tests (that are probably intermingled unless you were disciplined enough to separate them out at the outset), you need to then write some sort of script or routine to take your development database, copy it, fill it with known sets of test data and make sure that your tests run against this. Oh, and don’t forget to make sure that any emails generated are not actually sent out. Or you could just type ‘rake’ and have it all done for you.

Ruby’s dynamic nature
Scaffolding makes for a great demonstration. But my favourite Rails example is Person.find_by_first_name_and_last_name_and_email_address(first_name, last_name, email_address). That’s a large chunk of your applications requirements automagically given to you by Rails without even thinking of Sql.

Deployment
We have a choice of deployment environments. Our own hosted servers running IIS (with some help from RForward) and SQL Server. Cheap, managed, hosting on Linux with Apache and MySql. Dedicated hosting on FreeBSD using LightHttpd and PostgreSql. Macs. Oracle. DB2. Choices, choices, choices.

Productivity
Because you are not repeating large chunks of code (“I’ve just added three new fields to the table, so I have to add them the stored procedure parameters, add the properties to the data-access object and add the properties to the business logic objects” versus “I’ve updated the migration and added a unit test“). Because the code is designed to read like English you can get on with your work with less syntax to get in your way (compare “DateTime tomorrow = DateTime.Today.AddDays(1);” to “tomorrow = 1.days.from_now“). Because Rails is designed to do, and optimised for, database-driven web-sites and nothing else – it’s not jack of all trades and master of none.

Confidence, Iterations and Change
Rails, being an agile development environment, expects that what you deliver will actually be significantly different to the original requirements brief. Because all the testing, fixtures and so on is built-in so deeply into the system, it becomes easy to follow agile practices. Decide on a small iteration of functionality. Deliver it. Get feedback. Change it. Refactor. Decide on the next iteration. Repeat. This makes job costing, on the way in, difficult but significantly boosts customer satisfaction, on the way out.

Cost
Visul Studio express is free. But will it offer everything that you need? Is your machine powerful enough to run a massive IDE? I can develop on a 7 year old iMac using Textwrangler and Terminal. Or on a 5 year old Win2K box using Crimson and the Command Prompt. If I need any extra tools they are a free download – normally a Gem.

Against Rails

Deployment
FastCGI is complex. RForward is immature. Rails wasn’t really designed with Windows in mind, although I have proved that it is feasible.

Green Fields
Rails depends upon convention. That’s what makes it so easy to use. However Rails can make life difficult unless you are working on a brand-new application. It is possible, just not as easy as it could be.

Knowledge
Until a few months ago I was the only person in the organisation who had even heard of Rails. Even now, I am the only one who knows about it in any depth. I have been told that we shouldn’t be using obscure tools that no-one else was using. But we are Basecamp subscribers. Other Rails sites include 43 Things, A List Apart, Icon Buffet, Cork’d and many more.

ASP.NET Postbacks
Some would regard this as an advantage but it has to be said that ASP.NET is an excellent workaround for some of the shortcomings of HTML. It may suck bandwidth as the entire view state is passed back and forth, up and down the wire, but the programming model is extremely simple for VB and Delphi developers to understand.