me

def Square Pegs in Roun...Square Holes

posted_by :Amos, :on => 'October 14th, 2008'

One of the greatest things about Ruby is being able to think outside the box. With every class open to change the possibilities become limited only by the imagination. Just today I ran into just such an issue...

Working with a lot of others that think strictly in a Java mindset leads to a lot of code that tries to jam functionality into the existing state of a library without changing the libraries classes. Today we were working with customizing views for ActiveScaffold. We needed to have colspans that were configurable for each column, and would be different for each model. We didn't want to have to do an override for each form so it really needed to go on the columns themselves. I stepped away for a short period of time, and when I cam back my pair had used the description field of an ActiveScaffold column to pass the colspan where we needed it. The code looked something like this:

class FooController < ApplicationController
 #code
   config.columns[:field].description = '2' #notice the use of a string in description because he forgot about duck typing
   config.columns[:field_two].description = '2'
 #more cool code
end

In the view he was then using the description as the colspan attribute. NOTE: My pair really is smarter than this quick workaround, I think he was hungry. We also needed to mark certain fields as required. I'm not sure how he was planning on doing this within those bounds. So I sat down and thought outside the confines of making my world jam into the ActiveScaffold idea of how things work, and I instead made ActiveScaffold understand my world.

class FooController < ApplicationController
 #code
   config.columns[:field].class.class_eval do
     attr_writer :colspan
     attr_writer :required
     def colspan
       @colspan || 1
     end
     def required?
       @required || false
     end
   end
   config.columns[:field].colspan = 2
   config.columns[:field_two].required = true
 #more cool code
end

I know that it isn't the cleanest right now, but tomorrow when I get in I'm going to put it in a module and actually call class_eval on the real class and not finding it with other methods. The point here is to not forget that Ruby is your tool. Don't beat a square peg into a round hole, bend the hole until it is square.

end

end