Tuesday, April 18, 2006

Pay attention to what you ask for

I have been busy debugging stuff on my rails project. I had a horrendous performance issue caused because I was retrieving way too much informaiton when I did x.find(). The development.log generated by rails is a god send to debug that stuff.

When you run into performance issues, it turns out that most of the time, rails does the right thing. If you putz around with the arguments to find and endup being greedy, thats when you get bitten in the ****.

The other cool thing I ended up using for this implementation is before_save() handler to allow me to do a webservice request while saving some data. That is so cool because now I dont have to track down all the places where save is being called or worse, implement save in the model.

Thursday, January 05, 2006

has-and-belongs-to-many with multiselect listboxes

If you have played with habtm in RoR, you might have encountered a need a provide a list that the user can select from. Usually, you would use a list of checkboxes to provide such a thing. Check out http://wiki.rubyonrails.com/rails/pages/CheckboxHABTM/versions/12 which shows a way to render such a thing.

But, It is a bit unweildy if you have long list that a user can select from, say, list of all cities in a state. In that case, I used a multi-select list box to provide such an implementation.

To generate the code, use the following method in your helpers. It basically takes 5 arguments, collection_name is a name for the collection that can be used in the controller, list_selections provides the collection of all possible selections, current_selections provides the current selection in the model, value_method is the method for the value, and text_method is the method for the text that can be called on the object contained within current_selections. Note that current_selections should have "include?" method implemented to determine the current selection.

def multi_select_collection(collection_name, list_selections, current_selections,value_method,text_method)
result = "<select name='#{collection_name}[]' multiple size=5>\n"
list_selections.each do |l|
result << "<option value='#{l.send(value_method)}'"
result << " selected " if current_selections.include?(l)
result << "/> #{l.send(text_method)} </option>\n"
end
result << "</select>\n"
return result
end

You might have to reformat it if you cut&paste since my blog might have wrapped it.


Wednesday, December 14, 2005

Rails is 1.0

Finally Rails is 1.0 product. If only I can convince my managers to use this for internal apps!

Monday, December 12, 2005

Changing app names in Ruby on rails

There is no trick to changing the application name from say "iteration" to "story"... Just search for iteration in all file names (because, Rails basically looks for controller based on the name and then maps it to the helper and the views) and replace them. Thats it. No funky tiles-config.xml to change or to re-deploy to yet another way... Rails is a beautiful thing!

Dependency breaking techniques from Michael Feathers book

This has nothing to do with Ruby as such. But I needed a place to keep this checklist of Working Effectively with Legacy Code interesting Dependency breaking techniques.

Working Effectively with Legacy Code


Adapt parameter - Shim Wrapper class around a awkward collobarator. Think HttpServletRequest...

Break out method object - Move large method to a class of its own with the local variables as the instance variables of the class and the method's argument initially is the host class. What is the point? It now helps us re-factor that class to expose its innards for extracting interfaces..

Expose static method - If the code under test does not need instance variables or methods to execute, expose that code as static and now you can test it lot more easily.

Extract and override call, factory method, getter - All about moving the awkword collobarator code into a method of its own and overriding it using subclass in test.

Extract implementer - Primarily for creation of clear names, push code from perfectly named class down one level and make the current class an interface.

Extract interface - Use tool support if available, safest way to break dependency. We saw problems where there are hierachies of objects and abstract classes in between current class and Object. Probably, Extract Implementer.

Introduce instance delegator - Basically useful for breaking dependency on a awkword static method. Create a instance method with same signature as the static and delegate. Replace the calls to static method with the instance delegator.

Introduce static setter - Seems like a way to get around static methods to work with singletons (such in Service classes). Basically, you need a static setter and make the c'tor for the object protected. Then we can construct the object by deriving off of the main object and setting that as the value of the singleton under test.

Parameterize constructor - Allow passing in objects that are normally created within the object. AKA Dependency injection.

Parameterize methods - pass in as arguments, objects that are used within a method.

Primitivize parameter - Basically move the code around so that the actual logic getting executed is using primitive types (ints, longs or in Java some of the primitive objects). Dangerous since eventhough it gets code to test, exposes internal details, duplicates data and also prolongs the problem.

Pull up feature: Useful if you have class that has dependencies that causes problem when instantiated because of dependencies. Pull up the class of methods to be tested to a superclass and derive the old class from this new super class. Test class also derives from the new super class and now you have access to those methods and can instantiated cleanly.

Push down dependency: This is similar to extract interface or subclass and override. Here we push down the problematic dependencies down to a subclass. This is opposite to pull up in that in pull up we are trying to get the methods out of the current class because there are many other methods that cant be tested because of dependencies and in push down, there are only few dependencies that are specific to some collobrarator that can be pushed down. This might need the callers to be modified.

Subclass and override: extention of extract and override.



Tuesday, December 06, 2005

HumaneInterface, Ruby and TDD

Ijust read the new entry By Martin Fowler about HumaneInteraces. Its pointing out that the Ruby language developers paid attention to end user need and came up with convienience methods even though it did cause bit of a method explosion. He used Array class and contrasted withjava.util.List interface. I agree with his post.
I would like to add to that test driven development tends to lead towards humane interfaces (The part about being having convinience methods be part of the object signature). I think that is because developers will end up thinking of a method to implement as part of the functionality and that is usually based on the input we usually consider for that method.

For example, lets say that you need to implement a method that would retrieve some information about an employee. We start off with a test with a method on the class, say, findEmployee(String name). Because, as humans, we tend to write code starting with the input and it usually is from a name.. Then we find out that the underlying collaborator (say EmployeeDAL) accepts only IDs. Now you endup with another method, say findEmployee(int id).. At this point, you endup with another method findIdForEmployee(String name). We can potentially remove the findEmployee(String name) since it can be achieved through a combination of findIdForEmployee + findEmployee(id). I contend that we should leave the earlier method as is since it provides a convenient interface to the caller.

My 2c..


WS-* in Ruby

Keith Brown has just posted a WS-policy implementation in Ruby. Nice! Does this make Ruby more and more a main-stream language for MS? Also, I wonder why Ruby is getting such an attention from Microsoft camp compared to, say, python?

Friday, December 02, 2005

BeautifulSoup and Ruby

I have been writing some simple script that would take a word HTML table and take out all that gunk attributes within the html leaving out only pure TR and TD elements. If you want to ask, I am doing this so that our FIT tables become a bit thinner. This also gave me a way to play with Ruby a bit

So, I looked around for a good parser for the HTML. I found BeautifulSoup port for Ruby. This is is truly a screenscraping parser but works beautifully. The coolest thing is that it allows for malformed HTML.

This is great.

yield keyword in Ruby, combined with "&" and .call are awesome.

Oh, I have started using Eclipse as my primary IDE for my ruby development and it helps a lot since it allows writing and running Test::Unit a breeze.

All in all, woohoo!

Thursday, December 01, 2005

Rails, Ruby, Eclipse

Whoohoo, Search and ye shall find. I found this "Ruby, Rails, Eclipse and a Link to Remember" which lead me to Setting up a Rails Development Environment on Windows Using Eclipse.

Now I can finally use my 2nd favorite IDE for all my Ruby work. Awesome, I can see my emacs-lisp code withering away slowly...


Ruby is fantastic

Some of the links I have been visiting..

  1. Rails Wiki
  2. Ruby Docs
  3. Programming Ruby Book


I am using Zoundry

I am trying out zoundry for editing my posts. Hopefully, this will work better than others I have tried so far.

I will post my ruby experiences here

I needed a place to post my experience with Ruby and Rails stuff. I have been having a blast learning this stuff. Just thought, why not have a place for my thoughts....
:)