Archive for the ‘Rails’ Category

Wednesday, May 21st, 2008

Sometimes, it’s worth stating the basics for all to see:

  • Follow the Model-View-Controller paradigm.  In particular, your views house your user-interface, your models handle the application and your controllers mediate between the two.  Controllers do not contain rules, conditionals dealing with business conditions, queries looking for objects related to the one in question.  All those things belong in the models.  
  • Use ActiveRecord conventions at all times.  It may not be the most efficient thing in the world but for most of you out there, it doesn’t matter.  
  • Use ActiveRecord and migrations to define and manage your database.  All your business related stuff stays in one place - the models - including defining relations (associations), validations and rules.  In particular, ActiveRecord associations makes some tasks easy (very simple many to many relations) and gives you things (such as polymorphic associations) that you can’t safely define using straightforward SQL.  With judicious use of validations you can ensure that the data stays safe.  
  • Use RESTful designs in your controllers.  This means that your controller very rarely grows beyond seven actions (index, show, new, create, edit, show, destroy) - and RESTful routing ensures that GETs and POSTs go to the right places.  If you need to extend things then add a sub-controller.  For example, if you were transferring an employee to another, you could have a route: /employees/1 for the employee him/herself, /employees/1/transfers/new to let the user define which company the employee is moving to and /employees/1/transfers/create to actually do the transfer.  And if you’ve defined your model correctly, the implementation of /employees/1/transfers/create should be as simple as @employee.transfer_to(@company)
  • Write your tests (or specs) first.  One - this gives you a series of small wins, which is good for your self-esteem.  Two - it helps to clarify your thinking.  ”I need to write something that does X and Y, resulting in Z … oh hang on, do I really need Y?  What about U and V?”
  • Use mock objects when testing your controllers.  Why bother coming up with lots of test data when all you really need to say is “if I the model saves correctly then redirect to X, if it doesn’t save then show Y”.  In the “transferring employees” example above, you only need to test that the controller calls “transfer_to” on your model.  Of course, your model will have already tested that transfer_to does what is expected of it.  
  • If you find yourself repeating a bit of code, or writing something similar then STOP and refactor.  Add methods to the application controller, create a new controller descendant, stick it in a view helper, add a module to your models, write a partial (and if it needs parameters, write a helper that takes a set of parameters and does the call to render :partial for you)
  • Did I say write tests and specs first?
  • Oh, and if it starts getting complicated you’re almost definitely doing it wrong.  
Monday, April 28th, 2008

I’ve had this before so I should have learnt my lesson. But I didn’t.

I had a site, inherited from another developer, that was migrated to a new server.

The other developer sent me the images associated with the site and I dutifully copied them over. I took a look - lots of “missing image” place-holders, but as this was a work in progress, in a database of thousands of items, I didn’t know what should be there and shouldn’t.

So I asked the other developer to check things over.

No - there should be much more than that” he said.

But look - they are there - in the correct folder on the server!” I replied.

You’re right, ” he said, “but why aren’t they on the site?

It turns out that the code for deciding whether to show the product image or the place-holder looked something like this (with superfluous guff removed):

if File.exists?("#{RAILS_ROOT}/public#{product_image(img, true)}") 
  "<img src="http://blog.3hv.co.uk/wp-admin/#{product.image_filename}" />"
else
  "<img src="http://blog.3hv.co.uk/images/products/image_missing.jpg" />"
end

I spent a while playing around, using script/console on the server (a truly fantastic tool). I asked it to generate the image tag for a given product - it returned exactly what I was expecting. I looked at the equivalent page in the application - it returned the image missing place-holder. But mongrel was running as the same user as script/console - there couldn’t be a permissions issue could there?

Then I remembered …

  • on my dev box, in console and/or test suites, RAILS_ROOT returns an absolute path
  • on my dev box, in mongrel, RAILS_ROOT returns an absolute path
  • on a typical Ubuntu server, in console and/or test suites, RAILS_ROOT returns an absolute path
  • on a typical Ubuntu server, in mongrel, RAILS_ROOT returns a relative path

That was the issue - the file system was getting confused as mongrel gave it a relative path for RAILS_ROOT (ignoring the fact that it should be able to resolve it, no matter how many double dots there were). And even worse, things appeared to be working fine until it was deployed to the webserver.

The fix is simple - add the following to your application controller:

helper_method :rails_root
def rails_root
  File.expand_path RAILS_ROOT
end 

and then replace all instances of RAILS_ROOT within your controllers, views and helpers with rails_root. Problem solved.

Sunday, January 6th, 2008

Normally I wouldn’t talk about Ruby on Rails on this blog. That geek talk is found on the tech blog instead.

Wondering?But, despite being about Rails, this isn’t a tech post. It’s about a problem that you will face when trying to hire a Rails developer.

Rails has a number of advantages.

  • It is a framework that gives you a massive head-start when building database-driven web sites.
  • It is designed to make programming fun. Meaning that the developers shoot through the work with a smile on their faces (rather than scowling and procrastinating).
  • It is opinionated and works much better if you follow the “Rails way” - that is a set of patterns and styles that are generally accepted as best practice within software development.

It is the last point that causes the problems.

You see, software development is still a relatively young industry. It is a craft, not a science. There are some who regard it as an art, maybe even a dark art. A lot of software development goes over budget simply because the staff are discovering new ways to do things - and you can’t budget for the unexpected.

But things are changing. Rails is proof of that. There is forty years of case history on the best way to solve certain kinds of problem. Most “business” applications are all about storing, retrieving and presenting information as easily as possible. The tricky, unknown, bit comes when you want to manipulate that data - but the majority usage is simple storage, retrieval and presentation.

And that is why Rails is great - it is designed to standardise storage, retrieval and presentation. It has rules that you should follow - and if you do your code will be elegant, reliable and on-budget.

The difficulty is knowing about those rules and why you should follow them. And herein lies the problem. When I discovered Rails (in the middle of 2005) it was a breath of fresh air. An environment that was about following the rules that we all knew we should, but never did. That actually made it easy to follow software-engineering-best-practice. That assumed you knew what you wanted to do and helped you do it. But the key was that I already knew the rules and why they were important, which in turn came because I had years of study and experience within my field.

If you hire a Rails developer tomorrow, how do you know that they understand those rules? Anyone can learn to program in Ruby - it’s a pretty easy language to learn. Anyone can knock together a few sites in Rails - it’s designed to get you started quickly. But do they know that your application logic belongs in models and not controllers? Do they know why your application logic belongs in models and not controllers? Don’t worry - you don’t need to know about models and controllers - that’s your geek’s job. However, if they can’t give a decent answer to either of those questions, they’re not a proper Rails developer. And you probably don’t know which questions to ask, let alone how to evaluate their answers.

Well, I have been using Rails, on commercial projects, for years now. The ideas behind it are second nature to me. I have seen how inexperienced developers can make a mess of a decent project yet still charge massive fees. I have seen how a project can take a wrong turn, when a simple explanation can change things for the better. How asking the right questions and looking in the right places can point you in the right direction.

So, if you are unsure of how your project is progressing, if you need to evaluate what your developers have produced, if your team is looking for guidance and if you want a series of specific recommendations for improvement then (although I am still finalising the exact details of the service) feel free to contact me today for more information on how 3hv can help. And, if you’re not quite ready, why not subscribe to make sure you stay up to date.

Update: You can read more about how this service works on the tech blog.
Photo: “Wondering” by bigevil600.

Monday, December 10th, 2007

Weird one here.

I was working on some code that had controllers within a namespace (Admin::ThingyController). The controller descended from an Admin::BaseController. And Admin::BaseController included a module (include GenericStuff), which in turn was defined within the Admin namespace.

So far, so good.

The code-base was actually somebody elses and the time came for me to add a new controller into the Admin namespace. So away I went: ruby script/generate controller admin/another_controller, editing the file so that Admin::AnotherController descends from Admin::BaseController.

Then, as I do, I filled out my functional tests, made them pass (ruby test/functional/admin/another_controller_test.rb) and then built up some (reasonably) nice views and examined them in my browser.

All good. The views worked, the tests passed, the controller did what it was supposed to.

One final check before committing to svn - rake. Bugger. A whole load of failures. What have I broken? Eh? It’s AnotherController that is failing. Check it in the browser. All good. Check the test individually. Row of dots. Try rake test:functionals. Blam!

To cut a long story short (actually the story is pretty short, it was the investigation that was long) the cause was the included module in the BaseController. What is particularly weird is that it was only AnotherController that had the failures, even though all the controllers within the admin namespace were defined the same way. Adding the new controller had upset the rake loader somehow.

And the fix? Change the include in BaseController from include GenericStuff to include Admin::GenericStuff (even though the admin prefix is not necessary as both GenericStuff and BaseController are within the same namespace). Now they all work - tests, rake and in the browser.

Friday, November 16th, 2007


After recently praising test fixtures as an important (but time-consuming) part of building your tests, there is something to watch out for.

If you get one of your foreign key references wrong in your fixture data you can get odd results. In particular I had a test that passsed when run using ruby test/unit/my_test.rb but failed when run using rake test:units.

The cause? Simple. I had two fixtures files, :orders and :work_items - where work_items have a detail relationship to orders (with a foreign key order_id). My orders fixtures looked something like this:

daves_first_order:   
  id: 1  
  some_field: whatever
daves_second_order:   
  id: 2  
  some_field: thingy
georges_important_order:  
  id: 3  
  some_field: wotsit

My work_items fixtures looked something like this:

first_line_of_daves_first_order:
  id: 1
  order_id: 1 # daves first order
  some_field: fish
second_line_of_daves_first_order:
  id: 2
  order_id: 1 # daves first order
  some_field: gerbil
first_line_of_georges_important_order:
  id: 3
  order_id: 4 # georges important order
  some_field: giraffe

Spot the error? It took me a while - and as I say, the only symptom was this odd behaviour where the test passed in one case but not in the other.

It turns out that the fault was this - one part of the test was creating a new order from scratch and assigning work_items to it. When run via rake the test database was torn down and rebuilt, matching the structure of the development database. Also meaning that every time the test was run, MySql new to give the next record in the orders table an id of 4. So the typo in the work_items fixture file (where first_line_of_georges_important_order has an incorrect order_id of 4) meant that the work_item pointed at the wrong order - leading to a cascade of further failures. For some reason, when run without rake the test passed as the order_id of 4 actually resolved to :georges_important_order (although I’m still not sure why).

The moral of the story? If you get odd behaviour, where your tests behave inconsistently, then examine your fixtures files in great, great detail.

Dog by kufrik

Thursday, October 25th, 2007

You know how it is - there are some things that you are just not comfortable without. My phone in my back pocket, my wallet in my front pocket, the key in the front door when I go to bed (just in case there’s a fire and we have to make a hasty exit), the dog under my feet (tripping me up), one of my large collection of jackets (current favourite: leather biker jacket).

And so it is with Rails projects. Before I do anything I do the following:

  • Load the Exception Notification plug-in and configure it with my email address
  • Load the form_test_helper plug-in so I can confidently test my forms
  • Load the ARTS plug-in so I can confidently test my AJAX user interfaces
  • Load Markaby so my views are beautifully coded and semantically correct
  • Create the Rails session store within the database (rake db:sessions:create)

Of these, the one I really can’t do without is Markaby (although ARTS comes a close second). I don’t know what it is (apart from Why the Lucky Stiff is genius). I can’t stand looking at rhtml files any more - too many angle brackets for a start. Instead, my mabs are things of beauty - and as I write the code to produce the views, I find that they are more semantically correct as well. For example:

div.row do  label “Email Address: “  text_field :person, :email_address  p.explanation “Please supply a valid email address so that we can send you a confirmation email”end

As I’m writing the Markaby code, class names like “explanation” seem to fit naturally - the code reads better, the HTML is semantic and the CSS is simple.

What more could you want?

Thursday, October 18th, 2007


I did my little presentation on Rails last night. “Why Rails programmers are so smug?” in front of 30-40-odd geeks in 20/20 format.

The 20/20 was hard - for those that don’t know, it’s twenty slides, each given twenty seconds. It means you know exactly what you have to deal with, but fluff a single line and you lose a slide. My talk went well (I think I hit the twenty seconds every time), although necessarily, it was a bit basic. I was surprised to hear people say that “Rails was too OO for them to learn” though.

The really interesting bit came after, when Lee Strafford gave a quick five minute talk on Project Sahara (Facebook link). Basically Lee doesn’t need to work since selling his ISP, PlusNet, so was looking for something to fill his days. He said that his favourite part at work was getting the geeks together and getting them to build stuff. So that is what Sahara is about - connecting the small, innovative geek companies (mainly in the North of England) with the suits with the cash. In such a way that as much control as possible stays with us. A great idea (along with Paul Robinson’s Vagueware) and worth a few minutes of your time.

Beer by elkojote

Tuesday, October 2nd, 2007


I remember years ago, when Object-Orientated Programming became fashionable, every single text on it (at least those that I could be bothered to read) repeated the mantra “OO is about inheritance”. Of course, that’s rubbish, but when you’ve been dealing with structs in C or Cobol it’s probably an easy way of thinking of things - objects are these data structures with these extra bits.

Nowadays, I rarely use much inheritance, beyond extending what my framework gives me. And I find myself using it much more in statically-typed (compile-time type checked) languages. I think splitting my functionality into a web of tiny objects gives me much more flexibility (as opposed to ending up with a couple of huge objects with layers of functionality added through generations of inheritance). Think of a chain of people - you ask a question of A, who in turn asks her friend B, who in turn asks his boss C, who in turn asks his wife D. In a different situation you may ask the question of B who gets the answer off A. Each of A, B, C and D is small and simple with a tiny public interface. Compare that to asking every question of an ABCD amalgamation - large and unwieldy with a large public interface.

Of course, Ruby does allow inheritance. It’s not always needed for reuse as you have mixins, but there are times when it is useful. And Rails lets you use inheritance in your models - it’s not always needed as, for joining disparate classes together you can use polymorphic associations, but there are times when it is useful.

So now I’ve tried to warn you off, how do you do it?

Imagine an address book application. You have basic AddressBookEntries which fall into two categories - People and Companies. This is an excellent candidate for inheritance as there is a fair amount of stuff shared between People and Companies (name, address, telephone number) but also some different stuff (People belong to Companies, Companies have a list of People and a VAT (tax) number).

To start with you create a model - AddressBookEntry.

Your migration may look like:

create_table :address_book_entries do | t |  # system fields  t.column :created_on, :datetime  t.column :updated_on, :datetime  t.column :lock_version, :integer, :default => 0  t.column :type, :string  # common fields  t.column :name, :string  t.column :address, :text  t.column :telephone, :string  # person specific fields  t.column :company_id, :integer  # company specific fields  t.column :vat_number, :stringend

Note that we have split the fields into different sections - system fields, common fields, person fields and company fields. Not strictly necessary but a nice to have.

Our model looks like this:

class AddressBookEntry < ActiveRecord::Base

end

But where are our people and companies?

Two new model files - person.rb and company.rb are needed.

# person.rbclass Person < AddressBookEntry  belongs_to :companyend# company.rbclass Company < AddressBookEntry  has_many :peopleend

There you go. All done (apart from the unit tests).

So how do you use this?

Simple - create a company and a person.

tiny_co = Company.create :name => ‘Tiny Co’, :address => ‘Tiny Towers’, :telephone => ‘4321′, :vat_number => ‘987654321′

dave = tiny_co.people.create :name => ‘Dave’, :address => ‘22 Acacia Avenue’, :telephone => ‘1234′

If we now look at our table we will see the following (some fields omitted because I’m lazy):

id type name company_id
1 Company Tiny Co null
2 Person Dave 1

The key is the “type” field we added. Rails treats this as one of its special “magic” fields and when you create an instance of Person or Company, Rails fills it out for you. Likewise, if you call AddressBookEntry.find(1) it will return you an instance of Company (not AddressBookEntry) - it uses the type to govern what it instantiates.

This means that Rails hides most of the mechanics of inheritance from you - you just write your models and they automagically do the right thing. There are some issues - your fixtures have to contain all descendants in a single file (in this case address_book_entries.yml) and it is perfectly legal to write dave.vat_number = ‘54321′ (as the vat_number field, which technically belongs to a Company, not a Person is still accessible to all AddressBookEntries).

But Rails has made inheritance in a database about as easy as I can imagine. There is a little bit more to inheritance - with ActiveRecord abstract classes, but that’s a story for another day.

Photo by spektator

Wednesday, September 26th, 2007


Migrations are great. Not perfect but pretty damn good. Certainly better than my previous experiences of handling databases (grab the structure from dev, compare it to qa and then construct a script to move from one to the other - if you are lucky with a tool like Sql Compare, if you’re not then by hand).

But there is a hidden time bomb in there. You see, when you are writing your migration you, your migration and your models are at a particular point in time. But when you deploy your application your migration and your models are at different moments in time. Confused?

Let’s run through an example. It’s August 2007 and your production application is on migration version 12. Your model files, dated August 2007, have lots of nice (unit-tested) validations all set up and ready to go. Fast forward to October 2007. Your production application is still on migration 12 but your development version is on migration 18. Your subversion repository contains a load of model files dated October 2007. It’s time to deploy. You type cap deploy_with_migrations and the migrations fall over at the data insert script, number 13 (unlucky eh?).

So what’s going on?

The thing to remember is that when you are writing the code, the migration and the model are in sync. But when you come to deploy the code they no longer are. cap deploy_with_migrations grabs the October model files out of svn and then runs the migrations one at a time (after inspecting schema_info) - starting with migration 11, then 12, then 13 then BOOM! The problem is that migration 13 is dated September 2007 and is expecting the models from September 2007. But svn has just faithfully grabbed the models from October. If migration 17 adds a new field and the October model has a validation that enforces a rule on that new field - when migration 13 tries to instantiate and save an instance of that class, the (future) validation rule fires and fails. As the field does not yet exist.

So how do we solve this?

It’s a bit of a hack but we can rely on Ruby’s dynamic nature. Just stick a dummy class declaration at the top of your migration file whenever you need to do data inserts.

class MyModel < ActiveRecord::Base

end

class MyMigration13 < ActiveRecord::Migration   def self.up    MyModel.create :field => ‘value’  end  def self.down    …  endend

When MyModel.create is called, it is using your “locally” defined ActiveRecord::Base descendant and not the one in app/models - meaning that whatever validations you have applied (in the future) do not apply. Of course this also means you can screw up the data - but, hey, nobody’s perfect!

Polar bears by Marja Flick-Buijs on stock.xchng

Wednesday, September 26th, 2007

James Hoskins makes a good point, on the North West Ruby User Group mailing list, about the recent Rails to PHP switch.

This my friends is what seo’ers call link bait. Notice the nice digg friendly title with a low number at the beginning followed by a lovely language war headline? Story goes up four days ago, story submitted to digg 3 days ago, look here:

http://digg.com/programming/7_Reasons_I_Switched_Back_to_PHP_After_2_Years_on_Rails_2

Story also forms basis for article at the register:

http://www.regdeveloper.co.uk/2007/09/25/ruby_rails_scripting_project_failure_2_0/

O’Reilly is going to push a whole load of ads on the back of this - plus all the link love - and CD Baby is going to get a whole lot of exposure.

Online marketing, you have to love it.