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.