Posted by Doug
Thu, 23 Jun 2005 13:35:00 GMT
Honestly, Object Oriented Design is something I don’t get a chance to practice very often.
Ruby on Rails encourages
OOD with it’s fundamental
MVC functionality split. What that’s typically meant to me is that every database table gets an ActiveRecord model, and every model has it’s own controller which drives some number of views.
Reading
Dave Thomas’ new
Agile Web Development with Rails has broken that mold a little for me. Rather than focusing on a strict one model has one controller, Dave illustrates using controllers to group similar actions together. It seems obvious that’s what controllers are for; but, Dave’s book is the first place I’ve seen break the static tie between models and controllers.
My project has an Image model. Users have many Images and Images belong to Users. I store Image filenames in the database associated with the User’s id. I also store the image file itself on the filesystem. Using
Imlib2-Ruby bindings, I also parse the image to find things like width and height (to make proper image html tags) and scale the image to appropriate sizes. I’ve struggled with this object for not very good reasons. Yesterday I
blogged about making progress on this at the sacrifice of tests.
Last night was another “breaking the mold” learning experiences. I told
MarkWindholtz about my testing struggles. He suggested we pair up to work on it together. What a valuable experience that was! He had me extract out the two main groups of non-database-specific Image functionality; ImageFiler, the part that deals with the filesystem; and (for a lack of a better name) Imager, that’s a simplified front-end to the Imlib2 functions. The original Image model contains these other two classes and delegates specific functions to them.
This allowed me to test those other functions without having to worry about the database. I was struggling with what type of data fixtures to use when testing image scaling. I didn’t want to have to go through the work of making valid Image objects just so I could scale the image. With it broken apart it’s much easier to just test the individual pieces. It’s de-coupled.
I had been lumping everything related to a given database table into a single ActiveRecord object. So far, it had worked out pretty well. The problem is when your models get more complex. It becomes hard to test the models with the database functionality in the way. I’m not exactly sure where the line is between adding functionality directly in the AR model and putting it in a aggregated class. I guess you can tell when it needs to be extracted by how ugly your testing ends up.
To Dave Thomas’ credit, his Rails book also has an example of this. It’s not exactly the same, but his tutorial includes a primary model that’s not an ActiveRecord.
One of the things that’s exciting about
RubyOnRails? is that you actually get to do object oriented programming.
Posted in Ruby on Rails | no comments
Posted by Doug
Tue, 21 Jun 2005 15:51:00 GMT
I have a confession to make. I coded a bunch of stuff last night without writing any tests. I feel horrible.
MarkWindholtz says the feeling won’t go away until I write the tests.
I typically code and test at the same time. Only occasionally do I write tests first. But I rarely test in the browser before I’ve written both unit and functional tests.
Ruby on Rails encourages you to write tests. It’s usually not that hard.
I’ve been struggling with some image handling code in my commercial Rails project (more on that later). It’s been several weeks with no progress. I’ve had to redo this code several times.
I had copied some code I wrote for
RailsDay image manipulation. Unfortunately, that code was dependent on Image Magick. The Ruby bindings for Image Magick depended on a newer version of IM than what my server, running Debian Woody, had. The level of effort of upgrading that box to the newly released Debian Sarge was too much.
So, I did some hunting and found I could install Imlib2 and its Ruby bindings without too much headache. I started hacking on my old
RailsDay Image Magick based code trying to get it working like I needed. The problem is the code for
RailsDay has different requirements than what I have for my project. It was more complicated than what it needed to be. There was a lot of indirection that was driving me nuts.
So, I did something Mark has encouraged me to do before: I threw out all my code. My partner, Dave, was a little stressed by this. I didn’t totally throw it away. I just did a fresh checkout from
CVS and put my old working directory aside. That’s when I quit testing.
Dave was concerned about me starting over (again) and I wanted to get this stuff done faster. So, I started doing what some call “Interface Driven Development”. I started adding code to my
HTML views and then started filling in the backend to make that code work.
In about four hours I managed to get all my image handling working except the part for which I actually need Imlib2. Both Administrators and Users can upload images to their profile. Both admins and users can delete images from profiles. Images upload by admins are automatically approved. Images uploaded by users are automatically not approved. Administrators can view the list of not approved and can either delete them or approve them.
I think there’s still a few odd cases that need working out though. The main thing is I’m not scaling the images as thumbnails or a standard image size. Also, there are some issues with informing the user their image was disapproved and allowing users to delete their own not approved images before the admin gets around to it.
I don’t think I’m going to do much of that until I get tests though. Maybe my partner, Dave, will pair up with me to work on that together. Writing test code for handling file uploads is tedious. It always helps to have company when doing tedious work.
Posted in Ruby on Rails | no comments