Archive for the ‘Ruby’ 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.

Tuesday, March 4th, 2008

The Second Leeds Ruby Thing happens on Thursday the 6th March at Mr Foley’s, purveyor of York Brewery ales. No agenda, just excellent beer and talk about Ruby, Rails and all things geeky. And I promise not to talk about punching dogs again (ok - maybe that’s taking it too far).

As a taster, here is an example of the kind of quality guest you can expect: Gravy in yer Server.

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.

Sunday, September 16th, 2007

Recently we needed to run some tests against our application. However, the application shells out and uses a couple of Unix commands to do some of its work - commands that were not installed on my dev box at the time. Rather than ignoring failing tests (something, like ignoring warnings, I find really hard to do) I thought I should alter the tests to only run if the Unix command was present. After some discussion with Peter he came up with the following syntax:

using :some_command do   some_workend

Pretty nice - if some_command is available then the block is executed, otherwise nothing happens.

(By the way, the code below is (c) 2007 Rahoul Baruah and is available under the LGPL and is not the same as the code that actually made it into our application. [Legal stuff over])

require ‘open3′

module UnixTools

  def using command    raise “USING: you must supply a block when calling using” unless block_given? 

    installed = false    Open.popen3(”which #{command.to_s}”) do | stdin, stdout, stderr |      line = stdout.readline.chomp      expression = Regexp.new “(.)*no #{command.to_s} in(.)*”      installed = !expression.match line    end

    return (installed ? yield : false)  end

end

Stick this in a file called “unix_tools.rb” in your lib folder, make sure which is on your path and use!

One caveat - Peter started getting EOFs - because he was using the version of which that came with Fink. which on OSX returns “no COMMAND in $PATH”, which on CentOS returns “/usr/bin/which: no COMMAND in $PATH” but which in Fink returns EOF. As soon as he switched to /usr/bin/which it worked fine. YMMV, as ever.

Tuesday, April 17th, 2007

Mr Hansson has been winding people up recently, with his Twitter Controversy. But one of his more polite recent posts is about Seaside - a Smalltalk web framework that uses stateful objects on the server to allow a modal-style flow of control within your web application. One component receives a callback as the user clicks a link, it calls into another component and sits and waits until the second component returns control to the first - just like calling a subroutine.

I’ve made no secret of my love of Smalltalk - it’s what attracted me to Ruby and Rails in the first place. There’s a beauty about Smalltalk code (although please forgive any typos in the code below as I’ve not done any for a while) that you rarely see anywhere else, although Rails has it in places. I could go on for hours about:

  under21s:= people collect: [ person | person under21 ].  

Is that better than:

  under_21s = people.collect do | person |     person.under_21?   end

Not much in it. Ruby has the question mark - I like that as it makes the code read better. But Smalltalk has less superflous punctuation to make it read better still. And I love the full-stop to finish the sentence.

How about:

  nail needsHitting ifTrue: [ nail hitOn: #TheHead with: aHammer ].

Versus:

  nail.hit(:on => :the_head, :with => hammer) if nail.needs_hitting?

Ruby has the if at the end of the sentence, which I really like - and it’s even better when using unless. And Smalltalk has its slightly weird “everything is an object or message” ifTrue: method on the true and false instance variables that lead to something that is a bit less readable than the Ruby. But Smalltalk doesn’t need the parenthesis. And blocks are passed as normal objects (not weird add-ons that may or may not be tacked on to the end and sometimes implicitly converted to Procs). And if is not a reserved word.

Recently I’ve noticed the Smalltalk creeping into my Ruby style. Things like:

  validate(course, :against => template, :on => this_date)

Which is reasonable. But the brackets just kill me.

And then I had to write this:

  form_for(:course_template,     :url => course_template_path(@course_template),     :html => {:method => :put} do | form |     # form.stuff  end

It’s awful (yeah, yeah, I need SimplyHelpful).

What about, in config/routes.rb:

  map.resources(:course_templates,     :member => {:build_courses => :get, :do_build_courses => :post}) do | course_template |    course_template.resources(:course_details)  end

They really ought to read:

  courseTemplates:= map resourcesCalled: #CourseTemplates;    withAnAdditional: #GetMethod :called #BuildCourses :on #Members;    withAnAdditional: #PostMethod :called #DoBuildCourses :on #Members;    nesting: (map resourcesCalled: #CourseDetails).

Note: the nested call to resourcesCalled is actually sent to map, not to a nested object as in the Ruby original.

A literal translation would be:

  map.resources_called(:course_templates).with_an_additional(    :get_method, :called => :build_courses, :on => :members).with_an_additional(    :post_method, :called => :do_build_courses, :on => :members).nesting(      map.resources_called(:course_details)    )

The semi-colon chains method calls together (assuming each call returns the original return value from map.resources_called. But it’s really really ugly in Ruby.

The closest I can think of for this is:

  map.resources_called(:course_templates,     :adding => [      GetMethod.called(:build_courses, :on => :members),       PostMethod.called(:do_build_courses, :on => :members)    ],     :nesting => map.resources_called(:course_details)  )

which is a lot better but still pretty ugly (nested brackets - urgh).

Of course, map.resources is probably an instance of DHH’s syntactic vinegar - I’m sure that in his mind you should never add extra calls as it breaks the nice clean REST architecture. Well tough. I think myserver.com/course_templates/23;build_courses describes what I want very succinctly.

It’s definitely something that’s on my radar now … I want my Ruby and Rails code to be beautiful. Otherwise I may just be looking at Seaside in more depth.