Samuel Mullen

What could possibly go wrong?

Up and Running With Ruby Interactive (Ri)

Unbenownst to many Ruby developers, Ruby has a wonderful CUI (Composite User Interface) for referencing the API of the language and all available libraries: ri. ri stands for “Ruby Interactive”, which is an odd name for a tool to navigate documentation, and one which inevitably gets confused with irb (Interactive RuBy). Seriously, try Googling “Ruby Interactive”.

Perhaps it is due to the popularity of editors such as TextMate or Sublime, or perhaps because it is the ease of finding documentation through Google, but it seems that most developers either don’t know about, or don’t use ri. I do, but I’m a command-line junkie and I’ve not found another tool which is as simple or as accessible as plain old ri.

Getting Started

If you have Ruby installed, you should have all that’s necessary to play around with ri. If you are have troubles, look at “Troubleshooting” below.

To try it out, at the command-line type ri followed by the class or method you want documentation about. Typing ri Array should show you the docs for the Array class. If you type ri Array.min, ri will provide the documentation for Array’s min instance method. To be very specific about things, use a :: or # for class and instance methods rather than the generic ..

Example:

1
2
ri Array::wrap # class method lookup
ri Array#min # instance method lookup

One really useful feature of the tool is the suggestions ri provides when you enter only part of what you are looking for. Try it out:

1
2
3
4
5
6
7
8
$ ri Enumerable.each
Enumerable.each not found, maybe you meant:

Enumerable#each_cons
Enumerable#each_entry
Enumerable#each_slice
Enumerable#each_with_index
Enumerable#each_with_object

Neat. I didn’t know about #each_with_object.

In Technicolor

You may have noticed that all the documentation is in black and white - or at least you would have if you were using my color scheme. If you want to add a little color to your output, use the “ansi” format.

1
ri -f ansi Array.sort

If you like this, you can set up an alias in your .bashrc or .zshrc.

1
alias ri='ri -f ansi'

Make sure not to use a direct path to ri since RVM projects will have ri located somewhere else. You want to use your project’s instance of ri.

It’s All About the Interactive

It might surprise you to learn that “Ruby Interactive” actually has an “interactive” mode. You can start ri in interactive mode by passing the -i flag.

here’s what that looks like:

1
2
3
4
5
6
7
 $ ri -i

Enter the method name you want to look up.
You can use tab to autocomplete.
Enter a blank line to exit.

>>

At the prompt, just type in what methods, classes, or what-have-you and hit return. To exit, just hit return again, or the ever available ctrl-d.

Unlike calling ri with a specific parameter, interactive mode will, like an inquisitive child, keep prompting you to search again.

VIM and ri

It’s not always convenient to drop down to the command-line just to look up documentation. Wouldn’t it be cool if you could search the docs from your favorite editor? Daniel Choi thought so and created the excellent ri_vim plugin. It’s easy to install, but you will need to install it in each RVM project you want to use it in.

ri isn’t for everybody and that’s cool, but for those of us who are more at home at the command-line than in our own house, it’s indispensible. Try it out for yourself, you may very well find it’s more accessible and useful than you realized.

Troubleshooting

If you are not in an RVM project and you are unable to find ri documentation, try this:

1
2
gem install rdoc rdoc-data
rdoc-data --install

If you are in an RVM project, this should clear things up.

1
rvm docs generate-ri

Further Reading

A Letter From My Grandmother

My grandmother, Edith Pauline (Martin) Mullen, was born Oct 27th, 1906 and died on August 27th, 1976. That was three years after I was born. I never knew her or my grandfather, Silas Beryl Mullen, and I am convinced I have missed out greatly beacuse of that.

What follows is a letter she wrote shortly before her and my grandfather’s 50th wedding anniversary. There is nothing remarkable about her writing, she wrote down some highlights of her life; a life I will never really know much about.

I found it interesting that rather than saying she gave birth to one child or another, she said something like, “Paul Asher came to share our home.” Later on, when my uncle died at the age of six, she said, “Paul went away from us.”

I suppose what is more remarkable is what is not said. Contrary to what I assumed from the attached photographs, my grandmother didn’t have a negative bone in her body and she didn’t have anything negative thing to say about her life or those in it.

I wish she would have said more about my father, but I suppose it’s her life, not his. I did learn that he went to seminary for a year, but that is really the extent of what she wrote.

I would have like to have known my grandmother. But her faith is the same as mine, and I am convinced I will know her yet.


The Letter

I want to share with you some of the nice things that have happened along the way.

These have been very happy years. Oh yes! There have been times that were hard, but we had our love for each other to keep us close and our love for the Lord to guide us all the way.

When we went to Cincinnati we were so proud of our first apartment! The boys from the school came over one evening to greet us and share some treats. As they stomped up the two flights of stairs, the horrified landlady stood in the hall below and the teasingly told her, “We left our horses outside.”

We had lots of fun with the students at the seminary, but we learned lots of good lessons there too. These are memories that have carried us all through these years.

In the summer, we came back and lived with Mamaw and Uncle Tom until time to go back to school. In November after we went back to school, Paul Asher came to share our home. He was a beautiful child. We loved him so very much. He was always a sweet child. Many times I think, as I remember him, that if he had grown up, he might be like James today.

Then later, we moved back near Lafayette where Daddy worked on a farm. We bought our first furniture and furnished our little house. Uncle Arthur gave us a hen with some hatching eggs and we raised our first chickens. Different members of the family gave us seeds and plants so we had a good garden. I canned. I had learned that at home, so we put away some food for winter,

In the spring, Daddy got a job in Lafayette and we moved up on the back of the farm where Mamaw and Uncle Tom lived. Marilouise came to live with us there. Paul loved this baby sister and when I first saw her, I said to mother, “Isn’t she the prettiest thing you ever saw?” “well, I just can’t say that she is.” but she grew up to be a beautiful baby. Paul loved her so very much that even later in as much as he loved ice cream cones, he was willing to give her the last bite of his nice cream cone,

It was there that our good friends Margaret and Charles Spillman came to show us their new baby daughter, Irene. Margaret had been my beloved friend since before I started to school and all through a high school; in fact, all our lives; as long as she was with us.

From there we moved down to Cottonwood Corners and we had been there for some time, when Whaneta came to live with us. Oh the terrible storm that shook the country that night!!! It split the big cottonwood tree there at the corner there in half. This tree had been a guidepost for the early settlers as they moved across the Wea Prairie in their covered wagons. They always told them to follow the lines beyond the great cottonwood. That night, the cottonwood was split and now it is gone.

Daddy continued to work at Fairfield’s in Lafayette. Although he only made $19.95 a week, we thought that was a big wage and he had the best job in the family. Nothing to compare with the wages they are making today.

From Cottonwood Corners we moved to Stockwell. One morning, it was four below zero when Grandpa and Uncle Lester came with a truck to help us move over to Stockwell. We had a comfortable little home there and after we had been there for about a year, James and John came early one morning to live with us. Oh, they were darling, so tine, and so fragile. Aunt Rosilee and Daddy stood over the basket, almost constantly, for three days and nights to see that they didn’t choke. But! They grew up to be big men, but anyone who saw them that week would never have believed that they would be the big, handsome men that they are now.

We lived in Stockwell for quite a while and then we moved out in the country, south of Stockwell and Joseph came to live with us there. Aunt Lucy stayed with us that summer to help me take care of the children and do the work. For her wages, I bought her a pair of school shoes. Can you imagine that? Baby sitting wages? From the farm out there, that was the place where Paul went away from us. You know it was hard! It was very hard for me to accept the Lord’s will in his going away. It wasn’t until twelve years later at the breakfast table on Paul’s 18th birthday that I saw that the will of the Lord was over us all the time. Because that day he would have had to register for the service and they were sending over seas within three weeks after they were drafted.

Daddy was preaching at Clarkshill then. He was ordained there in 1933, the week before Paul went away. John Chase, his former college roommate came to speak at the church. Daddy was ordained then by elders of the Clarkshill Christian Church. He continued in that ministry for 47 years and he still continues to speak and to teach every opportunity that he has.

We moved into a little house in Clarkshill. It was closer to his work and it was a good home for the children. One evening, shortly after we moved, the children were playing outside and I went out to see about them. A little neighborhood girl said, “They are not supposed to be playing with me, ‘cause I have the whooping cough!” She had come over to visit them with the whooping cough. Soon, we all had the whooping cough.

We had friends in that community and that is where Marilouise and Wahneta started to school. They had a nice teacher and they learned very well. Samuel came to live with us while we lived there and soon after he came, everybody had the chicken pox. He had them very bad, but he got along and came through all right. The rest of them hardly knew they had the chicken pox.

We moved out into the country for a few months and then moved to Lafayette out on short Fifth Street, up the steps to the house. It was a cold house, but we got along very well there. Daddy had been ill and unable to work, so I had a job. I took Samuel and Joseph to nursery school as I went to work and brought them home as I came home from work. The others went to school at Highlands School and they all did very well. I was pleased.

Lafayette has been our home for many years and I have enjoyed living here; seeing the city grow and taking part in activities of the city while we were there, Nonah came to live with us. She was a sweet baby. I had someone take care of me, but she wasn’t a very good nurse. Wahneta was only six years old, but she fixed a cup of tea and brought it for me while I was in bed with Nonah. I will always remember that because she has been my cup of tea for many years.

Through those years, we went up North. Daddy was perching at Bethany Chapel. The people there were so very nice to us. One of the experiences I remember there: at home my different sisters had worked and they had taken turns buying a turkey for Christmas at home, I didn’t see how I could ever manage the money for a turkey for us to take out there. We went up to Bethany Chapel for the Christmas program. What a delight! Those lovely farm people had provided us with food; groceries, a turkey, a goose, chickens, steaks, and just EVERYTHING. I was so THRILLED, I could hardly believe it! They were the salt of the earth. I called Mother the next morning. She and the girls came in and got the turkey and goose to fix for Christmas dinner. We went out there and I was able to provide my share of turkey for the family. How much it means to have great Christmas friends like that!

Sometime late we moved down to Potter’s Hollow. It wasn’t a very nice house, but it was a beautiful place to live. The children had such good times, playing over the hills and in the cave down below the hill. It was here, while I was working that I found a good friend, May Lafon. She is still our friend and is in our Sunday School class at church. We have raised our children together. May stayed with the children when I went to the hospital to have Esther. Esther was a big, healthy baby and always did real well. We loved her very much, we still do.

Then with the help of our good friend from the church at Reynolds, where Daddy was preaching; Mr. Lane helped us to buy our first home up on Kassouth Street. We moved up there about the 4th of July, bought two big bundles of paper and started in to make a home of that house. It was a lot of work, but it was a lot of pleasure, too. We had such a nice time, fixing it up like we wanted.

It was while we were living there that Daddy went to school down at Indiana University for a short course. He had promised James that if he passed in school that year, that he would buy a bicycle for him, a NEW bicycle. And he did; on Saturday before he left on Sunday to go down to Bloomington to school. What a time I had portioning out the time so everybody could ride that bicycle. Joseph got up at daybreak, and took his turn before the others were up, because Joseph was just big enough to ride then.

That too, was the time when we went to the park on the 4th of July and lost Joseph, we hunted every place and we couldn’t find him. We stayed for the fireworks, but we couldn’t find Joseph. So, finally, we decided to take the children home and Daddy would go back to look some more, we even called the police to help us look for him. But before they found him, one of the neighbors found him playing out along the lake and came bringing him home in the night.

Oh, we had lots of fun at the park. One time, Whaneta had a new pair of shoes when she went up there. She took them off to go and play and left them by a tree. She had to come home barefooted because somebody else had found the shoes by the tree. Then the children learned to swim at the park. They went up a Lot and swam and learned to dive, later on Whaneta and Joseph took Red Cross fist aid life saving over at Purdue, that was not until later.

it was there that Lois came to live with us. We had a little bassinet for her and she was so sweet in that. The people at Reynolds were a little bit disappointed that I didn’t let them pick her up and handle her the first lime I took her to church. But she was rather a frail little thing and I learned at the hospital that babies were to be handled very carefully.

Oh, I forgot something that I meant to mention. The first time I took James and John to church, I took them both on one pillow when they were three weeks old to the Clarkshill Christian Church. They have been going along with me all these years.

It is a pleasure and a joy that I have on Sunday morning to sit with several of my children, grandchildren and even now, great grandchildren in church on Sunday morning.

There wasn’t much room to play in the yard around the house on Kossuth Street so Daddy started looking for a bigger place for the children. He found it.

Well, the first time we saw it, it did not look like the ideal location because there were so many weeds around that you could hardly see the house. But for 23 years it was our home at 1800 North 9th Street. It was from that home that the children went away to school, most of them to the seminary. Also, several of them were married from that home. I was a nice place because it was over an acre of ground and all the fields and the river behind us.

I can remember Joseph when he was getting ready to go to Japan, standing at the back window looking out to those hills. He said, “I’ve got to get my film enough to lasts me two years, of this view.”

Many times as I washed dishes or cooked or baked I front of that window, I thought, “I will lift up my eyes to the hills, from whence comets my strength.”

I have traveled many places, but to me, the view from the bypass hill is the most beautiful vi I have every seen.

The hills have changed, but still, their returning color each Spring, gives you courage that we often need.

All the neighbor children played in that yard, too. We saw them grow up and go away.

One day I drove into the drive and there were 21 children playing in our front yard. Can you imagine that?

Well, of course, it wasn’t long after that we had Philip and then we had ten of our own. As they stood around the bed and looked at Philip when I first brought him home, John said, “Boy, he is a regular football player!”

There was lots of room there as each of the children went away to school or work or to get married. One by one they got a room of their own. Sometimes I thought they could hardly wait! The other one got out of that room, so the next one could have a room of their own. Then finally, Lois was married from there. Then when she and Bill went to live at Valparaiso, where he was teaching and Philip and Joseph each had their own room and we had two empty rooms upstairs. Sometimes, when there was four in a room or two in a room, I wondered if there was every going to be room enough for all of them, but there was always room for them and for their many friends. Nice things to remember out there.

All the children but Samuel and Joseph took piano lessons, even James and John were in a piano concert once; can you believe that?

The joy we had of singing around the piano with Wahneta playing. One night they sang the Christmas carols in five languages as we always invited international students to our home to share in our Christmas and Thanksgiving activities. The boys who had come from Norway and South America and India and many other places joined us and seemed to enjoy it a lot. Our home was always open to missionaries and I felt that the children had a great opportunity to know the many different people they had the opportunity to meet.

They wen to church camp at Lake James and Cedar Lake and then we helped with the founding of Hanging Rock.

Always, there was someone going to camp or picking up and hurrying up and getting the washing done so they could go back the next day.

We were very proud one year when the grandchildren started going and James, Jr. was named camper of the week. Also Stephen was very active in the camp work. All this year there have been several of the children who enjoyed the camp work.

Daddy preached at Palestine and we all went there. We have some of our very good friends in that area now. He preached at Reynolds and we went to Monticello, to the beach, took a picnic lunch and spent the afternoon with the children swimming over there. Many, many happy memories.

We were so proud and happy when Marilouise was able to go to Cincinnati Bible Seminary. That’s where she met Harold. Later when they were married and lived in Cincinnati, I went down to welcome Stephen and take care of him.

Then later yet, James and John went. James didn’t stay very long because he had met Therese before he went down there. So he wasn’t down there long before he came home to stay. Then in the Spring, he and Therese were married. Wahneta chose to go to Purdue. She worked very hard all the way while she was going to Purdue. Then after that, teaching for a while and then down to Indiana University and working until she got her Masters and her Doctorate there.

Nonah went to the Seminary and so did Samuel for a year and Lois went for a while.

Philip decided after taking a little trip after he graduated from high school, that he wanted to go to Pacific Christian and so he was out there for two semesters. I think he got sand in his shoes when he went out there to the North American Christian Convention. He came back, and that fall went back for a semester at Pacific Christian.

Joseph chose to join the Air Force after he got his draft papers, so he did not go to college, be he learned a lot of things in his travels around.

Esther, after she was married and Max went overseas, went to Floral School in Chicago and learned to do florist work. She still does that and she is going to decorate for our Golden wedding.

Daddy worked very very hard to keep us in our homes and as the boys grew up and some of the girls, they helped him with his work. Besides the church work, he did outside work so as to have the nice things of life.

The children always had a big circle of friends and it was always nice to see them come and go and enjoy their friendship.

Once Summer, Nonah got a cottage at the lake and she had a boat and we spent quite a bit of time up at the cottage. Each evening, those who were at work would come up and they would water-ski or play in the water or swim. That was lots of fun!

We managed some trips to the State Fair; some trips to Florida when Max and Esther were living down there; later down to Miami when Nonah and Bud were living there and Satellite Beach when Bud was stationed there. We had some really nice times on our trips around.

One year we went to New Orleans at New Year’s time and that was very nice.

I got to go out East, my FIRST plane flight when Paulette was a baby and visited them in Springfield, Massachusetts. Then Daddy and Lois came out and brought me back in the car and that was my first and only sight of Niagara Falls, completely encased in ice. It was a beautiful sight.

There have been many highlights in my life. One time I went out to Denver when Wahneta was teaching at Boulder, Colorado, and we drove north up to Mount Rushmore. I stood still and beheld that great masterpiece. What a thrill it was!

Another great highlight was when we were visiting Esther and Max out at Norfolk and he took us at sunset out to the ocean when a fleet, the 7th Fleet was in. Forty-seven Navy vessels were lined up, side by side at sunset and far out on the bow of each ship was a sailor in his white uniform and as the bugle played Taps, they struck the flags and they went down as one. It is something that gives you a thrill that you just can’t imagine.

Another time was with Grandpa. I went out East to Nonah’s on the train and came back with her and Paulette and Suzanne. We came through Washington D. C. and we stood at the tomb of the Unknown Soldier and watched the changing of the guard. How my heart thrilled and again as we stood on the battlefield at Gettysburg.

Things like these are memories that cannot be passed on to others, but they are memories that we treasure.

We worked very hard at the establishment of the Lynnwood Church of Christ. For five years they met in our home. I had vacation Bible School on the front porch. Twenty-seven children attended one year. Then we helped to build the building at Sixteenth and Greenbush and went to worship there. It has been like another one of our children; we treasure our memories there very much. Daddy preached there for quite a while, then John came and preached for six years. And there have been several others and we have tried very hard never to miss a service, unless we were too ill to go at all.

Christmas dinners and Grandpa’s were always a great joy. The brothers-in-law laughingly say; that when you ask a Martin girl to marry you, you had to promise to take her home for Christmas. It has been almost like that with the Mullen family. Christmas Eve has been our special time. Time and again we have lighted a candle in the window for those who are away and cannot get home in time for Christmas.

our Christmas tree must always touch the ceiling. What fun we had a few years ago, when eleven of the teenage grandchildren came out and popped popcorn in the fireplace, then strung the popcorn and decorated the Christmas tree for us.

We always try to call those who are away on Christmas Eve and let them hear the noise and excitement that is going on.

Many other highlights come to memory.

Wahneta coming back from different excursions over the world and bringing the treasures and telling us about the places she has seen and the things she had done.

Joseph coming home after two years in Japan. We missed the train! We thought sure he would be on the big 4. Instead of that, he was on the Monon Line. When we got back to the house, he’d come home in a taxi. We were so ansious to hear all he had to say, we’d forgot about all the good food we had arranged. Finally he said, “When do we eat?” and we ate and we ate and we ate, and he talked some more. Then when we had talked till about eleven o’clock, he wen to the kitchen and got two big ham sandwiches and a quart of milk. He was nearly starved. He said, “I wasn’t going to pay ninety cents for those hamburgers on the train!”

Another time when Wahneta came home, we were talking about her experience in Paris and all and forgot it was time to eat. I had supper ready. She said, “When do we eat? Do you know I have come from New York on one dime!” Well, they have always had plenty of food, waiting when they got here.

We met the plane once when Joseph came back from South America. He said, “You just lost #90,000.” He had himself insured and the plane come in safely.

Mark was with me that time. It was his first experience of going to the airport and watching the planes come in.

We met the plane one December morning when Philip came home from being at San Antonio for training in the Army. Sue came early that morning and went over to meet him, too. He looked so different in his snappy uniform.

We have sent them away to many places; Joseph to Japan, Wahneta to Hawaii and a trip to the Far East, Bud to Vietnam, and Max for several trips overseas, but the always came joyfully back to our fireside. We always gathered together the family to rejoice in their return.

I didn’t spend all my time taking care of the family. I did some things for the community too. After Philip started to school, I started working in PTA and for 31 years I helped with the Parent Teacher Association of this city, the area and the State. I had the honor of being on the State Board of Directors for the Parents Teachers Association and was made a life member. I represented Lafayette at the National Parent teachers Convention in Miami, Florida. That was my first trip to Florida. I have made many others; all of them have been very pleasant.

After PTA for 31 years and the children were all finished from school, I started working with the American Red Cross as a “Gray Lady” and for seven years I sered as a Gray Lady at Home Hospital and at the Soldier’s Home. I felt like that was a very worthwhile service because it meant so much to so many people.

I was asked to be a director at the Lafayette YWCA. I worked with lots of nice people there and enjoyed the work very much.

There were other organizations; CWPU, Lafayette Home Economics Club and Alpha Zeta Delta Mother’s Club. They have all made many friendships for me and I have enjoyed it very much. Also a member (only lady) on the Lafayette School Board.

The grandchildren came along and they were always a joy. It was fun to sit in the front window and watch them as the came up the walk and wave to me. There are so many, I just can’t tell about all of them.

And now the bring the great grandchildren for me to hold in my arms.

Philip and Sue brought Christopher almost three years ago on the way home from the hospital and let me hold him before they took him home. They are all a pleasure to me.

Now they are beginning to arrive from all over for the Golden Wedding Celebration on Sunday. How nice it is.

Five years ago I sent away three little girls to California and have not seen them since. The other day, they came back three beautiful young ladies and their two brothers, who will soon be eight years old, with them.

Wahneta will be coming on Saturday. Lois and her family will be coming on Saturday. Nonah is coming tonight and it is just a joy to welcome all of them. Joseph and his family are planning to come over and Samuel. I think they will all gather together Sunday in church and then Sunday afternoon for a family picture.

They have been good years. They have been happy years, I hope that we can have many more of them.

Daddy has always been so very good to me. Wherever he goes he brings me some choice gifts to remember.

We won’t be repeating our marriage vows. They have lasted for fifty years and the first ones are good enough for many more.

Guidelines for Using ActiveRecord Callbacks

ActiveRecord callbacks are awesome little devices which allow you to “hook” in to the life cycle of an ActiveRecord object. But from a quick Googling of “ActiveRecord callbacks”, you might not come to the same conclusion. Within the first ten results (as of this writing), there are four which are either looking for or providing ways of circumventing the triggering of callbacks.

Why would you want to skip callbacks? I can think of lots of reasons, but every single one of them is the result of models being too tightly coupled to other objects and responsibilities. Examples: sending emails, logging, updating related or unrelated tables, etc. If your callback stays within its object’s area of responsibility it should never need to be skipped.

Generally speaking - and I do mean “generally” - an ActiveRecord model has one responsibility: interacting with the database. When your model exceeds that one mandate, it immediately becomes more difficult to maintain. I would even go so far as to say that for every responsibility added to a model or any other object, the difficulty of maintenance doubles (No hard numbers; just shooting from the hip.)

To avoid this exponential growth in model maintenance pain, I’ve come up with three guidelines to determine if using a callback is appropriate.

Guideline #1: Use callbacks only if they can be run every time and in every circumstance they are triggered.

This rule is pretty straightforward, but let’s look at it for the sake of clarity.

Callbacks are executed every time their triggering event occurs (e.g. A before_save callback will be triggered before every save event). If there is any instance in which it shouldn’t be called, then think about moving the logic to a decorator object.

Consider also, context. If a callback cannot be issued in every circumstance (e.g. development, production, and test), that is a warning the callback needs to be refactored into something less coupled.

Guideline #2: Never create callbacks which exceed the model’s responsibility.

If a class has more than one responsibility, then the responsibilities become coupled. Changes to one responsibility may impair or inhibit the class’ ability to meet the others. – Uncle Bob Martin Single Responsibility Principle

As mentioned previously, the responsibility of an ActiveRecord model is to interact with the database. When we require our models to send emails, create files, or what have you, we exceed our model’s one responsibility. This doesn’t sound like a bad thing at first, but as requirements change - and they always change - the model will be required to do more and more in order to meet the added responsibilities.

By limiting callbacks to the scope of the model’s responsibility, we simplify maintenance and testing and keep the application prepared for further growth.

Guideline #3: If you have to stub callbacks during testing, you are violating one of the previous rules of thumb.

RSpec now has a nifty little method called any_instance which it inherited from Mocha. This method allows a developer to apply a bit of logic to “any instance” of a particular class. In the past I have used any_instance to keep my models from sending emails during testing. I did this because the emails were dependent upon more than just the one model and would therefore fail during unit testing. By stubbing out the callback I was saying 1) my callback couldn’t by executed every time and in every circumstance, and 2) it was exceeding the model’s responsibility. In other words I was violating the first two rules of thumb.

I’m sure there are valid reasons for stubbing your callbacks during normal unit testing (what some call integration testing), but in general, stubbing every instance of a callback in order to get a test to pass is an implication your callbacks have exceeded their responsibility.

I have said somewhat facetiously, “callbacks are the devil.” I usually say something like this after dealing with a callback which was doing more than it should. Callbacks, like any tool, can be exceptionally useful and are no more “the devil” than any other tool. It’s when we make our tools exceed their responsibility that they get a little devilish.

Further Reading:

Sending Notifications Using Decorators Instead of Callbacks

It seems that lately, many of the better Rails articles have focused less on Rails and more on Object Oriented development. Uncle Bob Martin noticed the same thing and at Ruby Midwest stated that developers have finally gotten over the excitement of the past couple of decades (i.e. the Internet) and have begun getting back to doing OOP correctly.

One article which stands out and which seems to have started a whole avalanche of similar articles is Harold Gimenez’s excellent Tidy Views and Beyond with Decorators. Although the article is primarily focused on the view layer, he does mention that decorators are particularly useful in other scenarios as well, “For example, you could use them to handle all the types of notifications should occur when saving a record without resorting to a nasty callback soup.”

That’s what I had been looking for, but I hadn’t realized it yet. It wasn’t until Avdi Grimm tweeted, “any_instance_of is an abomination :-P Albeit an abomination which sadly exists in RSpec now”, that everything began to fit together.

I have a couple models which send out notifications when they are either created or updated. I had been using callbacks to perform the notifications, but in order to get my unit tests to pass and to avoid the call to send notifications - they depend on information from multiple sources - I’ve had to stub out the callback method using RSpec’s “any_instance” method. I had any_instance stubs everywhere, and then to test the callback itself I had to unstub the stub. What a mess.

The solution, as you probably guessed, was to move the callback out of the model and into a decorator. Here’s an example of my original code:

Invite Model
1
2
3
4
5
6
7
8
9
class Invite < ActiveRecord::Base
  after_create :send_invite # callback

  private

  def send_invite
    Notifier.some_invite(invite).deliver
  end
end
Invite Unit Test
1
2
3
4
5
6
7
8
9
describe Invite do
  it "does something" do
    Invite.any_instance.stub(:send_invite) # stub here or...

    @invite = Factory.create :invite # ... this will raise an exception

    @invite.some_method_call.should be_true
  end
end

There’s no need to post the controller logic, since it’s just a normal save.

Here’s the new code without the callback (note: I’m using the Draper gem)

New Invite Model
1
2
class Invite < ActiveRecord::Base
end
Invite Decorator
1
2
3
4
5
6
7
8
9
10
11
12
13
class InviteDecorator < ApplicationDecorator
  decorates Invite

  def create
    save && send_invite
  end

  private

  def send_invite
    Notifier.some_invite(invite).deliver
  end
end
Invite Controller
1
2
3
4
5
6
7
8
9
10
11
class InviteController < ApplicationController
  def create
    @invite = InviteDecorator.new(Invite.new(params[:id]))

    if @invite.create # calling the decorator.create method
      # handle the success
    else
      # handle the failure
    end
  end
end
New Invite Test
1
2
3
4
5
6
describe Invite do
  it "does something" do
    @invite = Factory.create :invite # no longer need to stub the callback
    @invite.some_method_call.should be_true
  end
end

Now the model is only handling database communications (i.e. adhering to the Single Responsibility Principle) and not getting messed up with sending emails.

Since the callback is removed into the decorator, I am able to get rid of the any_instance stubs from my tests and just focus on the model, which means I no longer have to remember to stub out the notification method every time I need to create an instance of Invite. Testing the notification was simplified as well.

I still use the occasional callback when it is appropriate and when it doesn’t violate the SRP, but with the Decorator Pattern in my toolbox I’m no longer as quick to do so.

Further Reading

Hello, Octopress!

On a whim, I decided to move my wordpress site to Octopress.

I’ve managed to migrate all the content from the previous setup to Octopress, but the code snippets are jacked and the images are still pointing to WP. I’ll get this fixed in the near future. We’ll see…

Update: 20111231 - I’ve gone back through all my posts and fixed the images and code snippets.

Use Capybara::add_selector to Simplify Finding Links

In a recent post, Steve Klabnik argued that when writing Cucumber steps, we should base our selectors on the “rel” attribute of a link rather than using the traditional selectors (:id, :class, text, etc.). He argues that IDs shouldn’t be used because they are unique and don’t provide a general enough solution, and class attributes have everything to do with styles and nothing to do with semantics and data. His solution, as I’ve already mentioned, is to use an anchor tag’s “rel” attribute.

At the time of his writing, I also happened across Capybara’s “add_selector” method and was looking for an opportunity to use it. Steve’s article made for a perfect opportunity.

If you don’t already know, “::add_selector” “[Add’s] a new selector to Capybara” (shocking, I know). By using this method, you can simplify the way you find elements. So rather than using this:

1
2
3
num = 3

page.find(:xpath, ".//table/tr[#{num}]")

You might use something like  this:

1
page.find(:table_row, num)

Back to Klabnik’s post. Like I said, Steve thinks we should be looking for links based on their “rel” attribute. To do this in Capybara we normally have to do something like this:

1
find("//a[@rel='edit-article']").click

But rather than using this bit of xpath nastiness, let’s use Capybara’s “::add_selector” method.

I’ve created a “selectors.rb” file in my “Rails.root/features/support” directory and added the following finder:

1
2
3
Capybara.add_selector(:link) do
  xpath {|rel| ".//a[@rel='#{rel}']"}
end

Now, I can use this in my steps:

1
find(:link, "edit-article")

Not only is this easier to remember, but it reads better too.

Further Reading:

Tests Are Pain

Pain, really, is a wonderful thing. It’s a protective mechanism in the body which alerts us to something going wrong. It may be as trivial as a paper cut or intense as a broken bone, but regardless, pain lets us know that all systems are not “go”. Without pain, how would we know we had been injured or were sick? What kind of infections would we get because of unnoticed injuries? What risks might we take for lack of the fear of pain?

A computer program is kind of like a body which feels no pain. It doesn’t notice when something hurts, it just doesn’t work or it dies uttering some cryptic last words. If we’re lucky we can do an autopsy on the results, fix the problem, and bring our creation back to life. If we’re not, well, it may be a long night.

But what if there was a way to provide a sort of nervous system for your programs? A means of determining if a method would provide the correct results, and a way to know if your latest change affected something in another part of the program’s body? What could you do with that knowledge? Would you feel more confident in the code you released, knowing that your program had no hidden injury? Would you be more comfortable making sweeping changes to refactor a major class or database schema knowing that your program would tell you if something was wrong? And wouldn’t it be great to know about problems prior to pushing the “ship it” button?

What you want is a little pain. Tests are pain. That is, tests provide the same sort of mechanism in a program that pain provides in the body. If you couldn’t feel pain, you might have to do a regular visual check over your body to make sure there were no new injuries. Without a suite of tests, you have to do that same sort of visual check over your application….your entire application…not just the happy path….every time you change something.

When I first heard about Test Driven Development (TDD), it offended my sensibilities: Why would you write twice as much code? Why run a test knowing it was going to fail and then write code to make it pass, that’s backwards. It’s going to slow down the development process soooo much.

I’ve been developing applications using TDD for about a year and a half now, and I can honestly say my sensibilities were just flat out wrong. Here’s what I’ve found: * There was quite a bit of pain to ramp up, but not the pain of something going wrong, it was the pain of growth. * The initial development process has slowed down a bit because I’m writing tests, but the bugs have been drastically reduced, which means I’m spending more time developing and less time maintaining. * I think about the actual problem more, because I’m defining the behavior I’m expecting before I do anything else. * My code has become more modular, because its easier to test. This has the side effect of making better code. * I’m only coding as much as is necessary, which means my programs aren’t bloated unnecessarily. * Lastly, I’ve performed major refactors on current code bases with full confidence that my changes were going to work. I’ve even refactored a user table from one database into another. Could you do the same without tests?

No one likes pain, but it does serve a purpose in our body. When we feel pain, we know that something is going wrong and we need to take care of it. Computer programs don’t feel pain, but we can mimic the effects of pain with tests, and in doing so provide ourselves with greater confidence in our code.

As I alluded to, pain doesn’t always involve injury, sometimes it’s the result of growth. If you’ve not yet begun test driving your development, embrace a little pain and grow as a developer. Sometimes, “Pain is just weakness leaving the body.”

Test Driven Error Resolution

If you’ve been developing with Ruby on Rails for any length of time, you are no doubt familiar with Test Driven Development (TDD). You can use TDD in other languages - and I would encourage you to do so - but no other community I’m familiar with puts nearly as much emphasis on testing as the Ruby community. If you are unfamiliar with the concept, I invite you to check out the references in the ”Further Reading” section below.

Assuming you are familiar, then you know the drill:

  1. Write a test and watch it fail
  2. Write just enough code to make the test pass
  3. Refactor your code
  4. Repeat until your feature is complete

That’s a general summary of TDD and it’s where most articles end, but that leaves one crucial step out.

The part left out is what happens after you have deployed your product. TDD is a great methodology and it aids us in thinking through the problems we are trying to solve as well as reducing the number of errors in our product, but as they say, there are no silver bullets. We make mistakes, we misunderstand the client’s needs, we don’t account for how the user will use our application, and sometimes we just miss something. When that happens, errors arise.

When the inevitable error occurs you just tweak the “write a failing test” portion (Step 1) of the TDD cycle. Something is already failing, so you write your test to duplicate that failure. If you receive a notification that logins fail when users have “dash” character in their email address, then write a test which attempts to login in with an email containing a “dash” character.

After that, it’s TDD as normal. And so our new process looks like this:

  1. Write a test duplicating an error and watch it fail
  2. Write just enough code to make the test pass
  3. Refactor your code
  4. Deploy your fix

This is no great revelation, but oftentimes in our hurry to solve the immediate problem we forget, or lay aside, best practices. Don’t fall into that trap. Squash the bug, but do it with tests.

Further Reading

The System Is Borken

We are living in a system whose every aspect is broken. Not technology systems or even healthcare or political systems, by the whole system: from the subatomic to the lives we live to our interactions with others. And we know it to be true.

We see loved ones die from the ravages of disease and age, and we ask “Why?” We see men and women strive for - and deserve - greatness and yet they are greeted with defeat and failure time and time again, and we ask “Why?” We see criminals escape justice on a technicality, and we ask “Why?” Laws are created to curtail corruption, and yet corruption only increases, and we ask “Why?” Evil dictators rise to power on the backs of the people they subjugate, and the world applauds them, and we ask “Why?” We ask “Why?” and yet we know the answer: The system is broken.

But it is not just the systems we interact with which are broken, we ourselves are too. We know it when we fail or when we are weak. We know it also when are sick. We know it when we try to be “good” and wonder why we can’t accomplish a single good deed out of a purely altruistic desire. We know it best, however, when we fail time and time again to stop doing what is wrong; when, in spite of wanting to do what is right, we do just the opposite.

We are broken and the system we live in is broken, but why is the system broken, and is there a fix?

Setting Up a Remote Git Repository

Recently, I was asked by a client to help them set up their remote Git repositories and define a workflow which would work best for their small development staff. I’m going to write something up about the workflow I’ve suggested for them, but for now, let’s look at how to set up a remote repository.

For larger teams which require permissions to access projects, using a more involved system like GitosisGitolite, or Github might be a better solution, but for smaller teams, something simpler may be in order.

This post demonstrates how to easily set up a Git repository on a remote machine.

Prerequisites

You’ll need the following set up on the remote machine: 1) A user account which will have permissions to the repositories (I’m using “gituser” here); 2) public RSA keys to add to gituser’s authorized_keys file; 3) Git will need to be installed on the remote machine (duh.)

If you are not familiar with how to do this, reference the “Further Reading” section below.

Initializating the Remote

The first thing we’ll do is set up the remote machine. On your remote machine, change to the directory into which you want to set up your repositories. I usually install mine under “/usr/local/gits”. You can use the following command to do this:

1
sudo mkdir -p /usr/local/gits/new_repository

The “-p” option will create all necessary directories if they don’t already exist.

You’ll need to change the ownership of repositories directory to the gituser account:

1
sudo chown -R gituser:gituser /usr/local/gits

The “-R” option will change permissions (recursively) on the “gits” directory as well as all other directories within it. Remember that all future repositories will also need to be owned by gituser as well.

The last thing we’ll do is initialize “new_repository” as a “bare” repository:

1
git init --bare /usr/local/gits/new_repository

A “bare” git repository is “…a repository cloned using the --bare option, only includes the files/folders inside of the .git directory.”

Adding the Remote

Your remote repository should be set up now. It’s time to add it to let your local repository in on the news. From within your project, use the following command:

1
git remote add origin ssh://gituser@123.123.123.123/usr/local/gits/new_repository

“123.123.123.123” will be the IP address of the remote server.

At this point you should now be able to push to, pull from, and clone the new remote repository. If you experience an error here, it is likely because of a permissions problem or you have not added your id_rsa.pub key to gituser’s authorized_keys file.

Further Reading