Recent Posts

Q&A: ActiveRecord Observers and You

April 28, 2007

Yesterday, I wrote a short post titled, Observers Big and Small, about using Observers in your Rails applications.

The following questions were raised in the comments.

When should I use an Observer?

Eric Allam asks…

“Why not just use ActiveRecord callback hooks instead of Observers? Are Observers more powerful or is it just a matter of preference?”

Eric, this is an excellent question. I’d say that a majority of the time, using the ActiveRecord callbacks in your models is going to work for your situation. However, there are times that you want the same methods to be called through callbacks. For example, let’s take a recent problem that we used an observer to solve.

Graeme is working on implementing Ferret into a project that we’re developing for a client. With the use of Ferret, we can index and later search through content over several objects into a format that makes sense for our implementation goals. Each time an object is created and updated, we have to update our Ferret indexes to reflect these changes. The most obvious location that we can call our indexing methods is in each models’ callbacks, but this violates the DRY principle. So, we created an Observer, which observes each of the models that need these methods to be called. In fact, as far as we’re concerned, the fact that we’re indexing some of its data, is none of its business. We only want our models to be concerned with that they’re designed to be concerned about. We may opt to change our indexing solution in the future and we’d just need to rethink that at the Observer level and not change anything about the business logic in our models.

This is the sort of scenario when using an Observer makes great sense in your application.

Logging from an Observer

Adam R. asks…

“I’d also like the ability to use the logger from within an observer, but that’s another issue.”

I assume that you are referring to the logger method? I always forget to even use that method. I do know that the following works just fine in an Observer.

class IndexObserver < ActiveRecord::Observer
  observer Article, Editorial, BlogPost, ClassifiedAd

  def after_save(model)
    RAILS_DEFAULT_LOGGER.warn("Every single day. Every word you say. Every game you play. Every night you stay. I'll be watching you.")
    # execute something fun
  end
end

This will output to your log file without any problem.

This reminded me of when I used to want to log from Unit Tests.

(few minutes later)

Okay, I just attempted to use logger from an Observer and you’re right… it doesn’t currently work. There is a simple fix though, just extend ActiveRecord::Observer to add a logger method like so and require it in config/environment.rb (much like I did in with unit tests).

# lib/observer_extensions.rb
class ActiveRecord::Observer
  def logger
    RAILS_DEFAULT_LOGGER
  end
end

This will give you a solution to that problem.

class FooObserver < ActiveRecord::Observer
  observer Foo

  def after_save(model)
    logger.warn("I wonder if the #{address.class} knows that I've been watching it all along?")
  end
end

Observers Spy for Us

Most often, I look at Observers as being the guys that I hire to spy on my models. I don’t want my models to know that they’re being spied on and I’d like to keep it that way. They don’t solve all of our problems and it’s easy to overuse them. However, I have found several cases that they made a lot of sense and most of those cases have been where we’ve had the same things occurring in our model’s callbacks.

If you have other questions related to Observers, feel free to let me know. If you’re already using Observers, perhaps you could post a comment and/or blog post response with an example of when and how you use Observers in your Rails applications.


Observers Big and Small

April 27, 2007

My colleague, Gary, keeps a stack of Ruby and Rails books on his desk and was implementing an Observer into a client project. It appears that the Agile Web Development with Rails book is still encouraging people to do the following in order to load an Observer.

# app/models/flower_observer.rb
class FlowerObserver < ActiveRecord::Observer
  observe Flower

  def after_create(model)
    # model.do_something!
  end
end

Wouldn't it be cool if it?...oh wait.. it already does

April 23, 2007

Working into the evening on a client project (been sick and trying to play catchup) and was chatting with Allison about working in views and dummy text. I said, “Just make that a shortcut in TextMate.”

Then I thought, “I can’t be the first person to think of that.”

…as I type, lorem [tab]

Figures. Lorem ipsum generator… in TextMate. Why didn’t I know about this before?

So, I ask all of you… what’s your favorite TextMate trick?

Lately… I’ve been enjoying running single spec files with [apple]-r.

You Might Learn Something at the Back of the Train

April 19, 2007

I love to look at other peoples code. Initially, that’s what got me excited about Open Source software. Otherwise, I was looking at small snippets on various developer sites and really not getting the complete picture for how everything tied together.

Last night, I finally had a chance to checkout the sample caboose application, which was created as a way for people to get an idea for how some of developers in caboo.se are putting together their applications.

Some things that you might want to check out it’s using…

Authentication](http://weblog.techno-weenie.net/2006/8/1/restful-authentication-plugin)

It’s definitely worth taking 15 or so minutes to check it out and get some fresh ideas.

There are a few things that I’m not quite sure that didn’t quite make sense, so… perhaps I’ll submit a patch. :-)

svn co svn://caboo.se/plugins/court3nay/empty_apps/tags/v_003

Have fun!

Embracing Failure, part 1

April 10, 2007

I’m currently reading To Engineer is Human, by Henry Petroski and found the following applicable to software development and managing client and customer expectations.

“As much as it is human to make mistakes, it is also human to want to avoid them. Murphy’s Law, holding that anything that can go wrong will, is not a law of nature but a joke. All the light bulbs that last until we tire of the lamp, all the shoelaces that outlast their shoes, all the automobiles that give trouble-free service until they are traded in have the last laugh on Murphy. Just as he will not outlive his law, so nothing manufactured can be or is expected to last forever. Once we recognize this elementary fact, the possibility of a machine or a building being as near to perfect for its designed lifetime as its creators may strive to be for theirs is not only a realistic goal but also a reasonable expectation for consumers. It is only when we set ourselves such an unrealistic goal as buying a shoelace that will never break, inventing a perpetual motion machine, or building a vehicle that will never break down that we appear to be fools and not rational beings.”

I’m sure that most of us are guilty of having high expectations for products that we purchased. (why does my ipod screen scratch so easily when in my pocket?) We also set high expectations for the code that we develop, which is why we (hopefully) continue to refine our process. We’re bound to time and budget constraints, which often prevent us from testing every imaginable edge case. Given our constraints, problems are almost always going to arise. It’s no wonder that we see Test-Driven Development as an important part of a healthy development process. We want to catch our failures as early as possible.

Our clients often have high expectations and it’s almost always very reasonable. That’s not to say that some clients will not have highly irrational expectations. It’s our job to manage these expectations as best as possible.

Do we mislead our clients by convincing them that our TDD/BDD process is going to prevent any bugs from creeping from the woodwork after the development cycle is finished?

“I thought that we paid you to fully test the code?”

Really… is that even possible? Can we predict (and test) every possible interaction within an application? Highly unlikely.

What we can do is plan for and embrace failure. We can help our clients understand that almost every application needs to be maintained after it’s initial development cycle. Bugs are inevitable and there needs to be a clear process for handling them.

Perhaps I’m abusing the bug fixing process by calling it a failure… but I’ve also found that yes… many bugs are due to failure. Whether that be a failure to specify application behavior, a failure to understand the project goals, a failure in communication, …or maybe a failure in our software architecture. We’re constantly failing.. and it’s okay!

IT’S OKAY TO FAIL! (some of the time…)

“No one wants to learn by mistakes, but we cannot learn enough from successes to go beyond the state of the art. Contrary to their popular characterization as intellectual conservatives, engineers are really among the avant-garde. They are constantly seeking to employ new concepts to reduce the weigh and thus the cost of their structures, and they are constantly striving to do more with less so the resulting structure represents an efficient use of materials. The engineer always believes he is trying something without error, but the truth of the matter is that each new structure can be a new trial. In the meantime the layman, whose spokesman is often a poet or writer, can be threatened by both the failures and the successes. Such is the nature not only of science and engineering, but of all human endeavors.”

As we’re creating these virtual structures… are we really taking the time to reflect on our failures? This is why some teams adopt practices like iteration retrospectives and post-mortems.

I’ll end this with a few questions, which I hope that you’ll share your experiences about…

  • In what ways is your team embracing the failures of your development
projects?
```text
-   How do you help manage your clients expectations... so that they too
```text
can plan for and embrace failure? Isn't their new business venture
on the web... likely to experience some failure?

We have so much to learn…

Happy Birthday Allison

March 28, 2007

This morning was delightful. I woke up to find that 37signals had referenced our website on Signal vs Noise this morning. In particular, they referenced the Rails hosting order form on the PLANET ARGON site. What’s interesting is that Allison created this design over a year and a half ago.. and we’re actually in the process of a complete site redesign, which Chris and Allison are planning to blog about in depth. :-)

There are some discussions within the comments on the blog post about the design decisions that were made, some of which we’ve already begun to address in our redesign process brainstorming (based on google analytic conversion data).

On top of that, today is our Experience Director, Allison Beckwith’s, birthday.

Thanks for the linkage, 37signals!

…and… Happy Birthday Allison!

Do Your Views in Ruby on Rails need a cleaning service?

March 27, 2007

I’ve been working on a project with Graeme, and we’re spending some time cleaning up some RHTML views.

He posted an article earlier, titled, Dirty Views? Clean them up!, where he asks the following.

“I am also looking for more information on best practices with views in Rails. There doesn’t seem to be much information on the subject.”

We’re starting to re-evaluate how we approach our views and are curious what other teams are doing… especially if you have a team thats approx 1/2 designers… 1/2 developers per project. We’ll be reviewing some of the other options for the View layer over the coming week(s) and welcome any suggestions/insight to this area of Rails… head over to Graeme’s blog and share your thoughts. :-)

Staying home

March 26, 2007

So, the Microsoft Technology Summit started today, which I was invited to. I had to cancel my trip late last week so that I could help out the design and development team out on a project that we’re wrapping up. Our office has had some colds going around, so I’m putting in some extra time to help out.

If you were hoping to meet up with me on one of these evenings, I apologize. I may be heading up to Seattle in the coming weeks anyways and if you sent me an email, I’ll let you know when I am planning to.

To those at the MTS… have fun and keep us posted on what happens!

Review: Highrise, part 2

March 20, 2007

It’s been five days since I posted my initial review of Highrise, that shiny new application by our friends at 37signals. I’ve been getting adjusted to my new process of managing contacts and have had to remind myself a few times that there is a brand new tool that aims to make my life a little easier.

Contact Form Integration

I haven’t heard about a Highrise API available yet, but I will definitely be looking into tighter integration once that is available.

Direct Submissions (not yet)

It seems that Highrise isn’t going to allow direct emails to be sent to it, they need to come from an existing contact in your account. For example, our contact form sends an email to our customer service mailing list. At one point, we had it connected to the Basecamp API to submit each new contact request as a new message in a designated project, but it didn’t really give me what I was looking for. Since each user in Highrise has a custom dropbox email address, I thought that I would try to link up the contact form to submit directly to Highrise.

I got the following response back from Highrise. ;-)

Hi Robby-

An email was sent to your Highrise dropbox from
john@cusackforpresident.com. This address does not
correspond to any address that you have recorded
for yourself in your Highrise account, and so the
email was discarded.

So, in the meantime, I’m following this process with new contact requests as well as the other people at PA who are responsible for responding to Contact Requests.

Contact Request Submission

So… let’s say that John Cusack (one of my favorite actors while growing up) is having a weird dream and wants to get a website built for the record store that he ran in High Fidelity.

PA Contact Request
Form{width=”320” height=”500”}

He fills out the form and submits it, which our application than stores and also sends over his contact information to our customer service email address.

A few minutes later…

Manually Review in Mail.app (and apply 2-minute rule)

Here I am in Mail.app and doing a double-take… “is that the real John Cusack?” (no, it’s just test data).

Email in
Mail.app{width=”500” height=”347”}

I then ask myself the following questions…

  • Can I answer this in less than 2 minutes?
-   If yes, respond immediately (forward to Highrise, if contact
    info will be needed again)
-   If no, forward to Highrise
```ruby
Okay, so I've decided to forward this contact to Highrise as I decided
to go ahead and speak with John over the phone, since he was kind enough
to leave his phone number.

As I mentioned in my last post, I'm using
[Act-On](http://www.indev.ca/MailActOn.html) for forwarding emails to
Highrise.

(back-tic h)

[![Mail.app with
Act-On](http://farm1.static.flickr.com/160/428327106_c7b592290e_o.jpg){width="409"
height="101"}](http://www.flickr.com/photos/robbyrussell/428327106/ "Photo Sharing")

...and off the email goes.

## View/Edit message/contact in Highrise

I'm now logged into Highrise and looking at my dashboard. As you can
see, John Cusack is now at the top of my dashboad and waiting for me to
decide if I want to do something with it.

[![Highrise
Dashboard](http://farm1.static.flickr.com/169/428327762_70f622ac22.jpg){width="500"
height="216"}](http://www.flickr.com/photos/robbyrussell/428327762/ "Photo Sharing")

## Schedule Follow Up tasks

As I mentioned, I spoke with John over the phone and promised him that
I'd send him a follow up email with a proposed date/time for a meeting
next week.

[![Adding task in
Highrise](http://farm1.static.flickr.com/151/428327248_f7aa7f4e33.jpg){width="500"
height="496"}](http://www.flickr.com/photos/robbyrussell/428327248/ "Photo Sharing")

...and that's one way that I'm now using Highrise to getting all my
contacts organized.

## Five Day Review

Well, after five days of using [Highrise](http://www.highrisehq.com/),
I'm still impressed with it. Our Administrative Assistant began using it
last Friday and is using it to schedule follow up tasks for me. This
definitely beats the old process of leaving post-it notes on my desk
with names and phone numbers. :-)

We also upgraded to a paying account and paid for **invoice #4**.... and
I plan to hit contact #200 later today within our account.

A few bugs:

-   Forwarding email from Thunderbird doesn't currently work (as of last
```text
Friday)
```bash
-   A few forwarded emails from Mail.app didn't work right (garbled...
```text
html emails perhaps?)

Also… it appears that 37signals has opened the doors to the public earlier today.

Have fun!

Review: Highrise, part 1

March 15, 2007

So, today I got what I’ll call a platinum ticket from one of our pals at 37signals for their upcoming new application, Highrise, which is what they’d call a “shared contact manager.” The rest of you can keep hoping that you’ll win a golden ticket this weekend. ;-)

For the past year and a half, I’ve been wanting to build some sort of contact and task management tool for organizing all of the contact requests that PLANET ARGON receives about our Design and Development and Rails Hosting services. If I go away for a week, I come back to a huge backlog of people who may be waiting a response from me. Having a tool to allow others at PA to see what is in my queue and in some cases, respond on my behalf… has been needed. When I first heard about Highrise long ago, I got excited and have tried several different tools and each of those tools has left me feeling uneasy. Perhaps I’ll post some reviews of the other tools one day.

First Impressions

The signup process looks familiar… :-)

highrise
signup{width=”446” height=”175”}

Look and Feel

Well, it definitely looks and feels like a 37signals application. There might have been a time when I thought that would be silly… but really, when you look at other product suites, consistency is extremely important to the user experience. While they are definitely going to attract people to Highrise who have never used any of their other products, I’d also expect a huge majority of their initial customers will be users of their other products. It’s obvious that Highrise was in response to a void in the market that people (likely customers) were asking for in other products like Basecamp.

Highrise has all the Ajaxy goodness that you’d expect in a brand new modern web application. Most of it seems very intuitive, but I found myself getting caught up on the extra tabs across the top of the screen. When new tabs appear, my natural response was to try to close them when I was finished looking at the page. Perhaps this is just a design decision that I’ll learn to really like. At the moment, I’m still not quite sure because I expect the tabs to change quite frequently.

Highrise
tabs{width=”500” height=”29”}

(few minutes later)

Actually… I wonder if the interface designers at 37signals did this to help their users avoid having several tabs open in their web browser. I use Safari for Basecamp and generally have 5-8 tabs open throughout the day for different projects that our team is working on because the Dashboard view doesn’t really give me a good feel for what is happening throughout the day on our various internal and client projects. I’ll try to pay attention to my usage habits to see if I’m opening less browser tabs in Highrise.

So far, this is the one thing that I’m not quite sure about (yet).

Highrise meets Act-On

Once I saw that you could forward emails to Highrise and it’d auto-magically create a contact and store it, I jumped for joy (not literally… but I got an evil grin). I have been using (more like heavily relying on) Mail Act-On for what seems a really long time. I’m constantly forwarding emails off to my colleagues to keep things from sitting stagnant for too long. So, guess what I did?

Mail Act-On +
Highrise{width=”358” height=”102”}

This is working beautifully and allowed me to move about 20 contact requests to Highrise in just a few minutes.

With this new ability, I can remove that one project in Basecamp that I was using to collect contact request information. That information now has a proper home!

Manage your Peeps

PLANET ARGON
peeps{width=”267” height=”395”}

I’m taking more screenshots and going to continue putting more of our contacts into Highrise… so… consider this part one of a short series of posts.

To be continued…