Read my latest article: 8 things I look for in a Ruby on Rails app (posted Thu, 06 Jul 2017 16:59:00 GMT)

Sending email: Controllers versus Models

Posted by Mon, 16 Nov 2009 14:33:00 GMT

While reviewing some code recently, I came across controller code that resembled the following.

if @customer.save
  CustomerMailer.deliver_welcome_message(@customer)
  flash[:message] = "Your account has been successfully created. We've sent you a welcome letter with..."
  redirect_to dashboard_path
else
  ...
end

Fairly typical Rails code. Nothing alarming here, but I wanted to evaluate the call to the mailer in this scenario. When it comes to sending emails from your application, you can choose to do it from the controller as in the example above or in your models. Our team prefers to do this from our model via a callback as we are considering this to be part of our business logic.

Each time a customer is created, we want to send them an email. This can be moved into the model and resembled something like the following..

after_create :send_welcome_message #, other callbacks..

def send_welcome_message
  CustomerMailer.deliver_welcome_message(self)
end

There are a few benefits to doing it this way.

  1. We can test that this is being triggered within our model specs instead of our controller specs. (we prefer to spend more of our time working within models than controllers)
  2. We remove the dependency that all requests must be processed through our controllers.
    • Example: We may one day create rake tasks that data and want these emails to still be sent out. (We’ve had to do this a few times)

I definitely don’t think doing this via controllers is a bad idea, I just lean towards keeping controllers as dumbed down as possible. This allows us to have less controller code that is focused on passing data to/from models and letting our models do the heavy lifting.

UPDATE: DHH was kind enough to post a more detailed response on his blog.

Flash Message Conductor

Posted by Fri, 29 Aug 2008 20:35:00 GMT

Do you find yourself copying and pasting the same code from Rails application-to-application as new projects start? Our team has a handful of projects in development right now and we notice that some of these reusable components tend to get out of sync when we bounce between projects. So, we’re making an effort to spot these and are creating a handful of plugins so that we can keep them updated between projects. (I’m sure that a lot of you do this as well)

In an effort to share some of our patterns, we’ll try to release them into the wild for others to use and perhaps if you have better patterns to offer, we’re always interested in improving our approach.

Introducing Flash Message Conductor

Over the years, our designers and developers have approached the management of flash messages several different ways. In Rails, the default way to add something to a flash message is to do something like this in your controller.

flash[:message] = "You have successfully signed in to your account."

What we began doing a while back is to create a few controller helper methods:

add_message( "You have successfully signed in to your account." )
add_notice( "You've Got Mail!" )
add_error( "Oops! Something got fucked up!" )

Really, nothing too crazy here, just a pattern that our developers have preferred to managing our application’s flash messages.

Okay, so now for the part of the puzzle that we aimed to make consistent across our projects. Rendering flash messages would usually result in several lines of conditionals in our application layout to check if the flash had any values assigned to it. As we worked with our HTML/CSS designers to define a consistent pattern, we moved our code into a helper for rendering flash messages.

With Flash Message Conductor, we just need to pop in the following into our application layout.

<%= render_flash_messages %>

If we had called add_message, it’d render the following:

<div id="flash_messages">
  <p class="message">You have successfully done XYZ...</p>
</div>

Or, should you have called add_error, it’d render the following:

<div id="flash_messages">
  <p class="error">Oops! Something went bonkers!</p>
</div>

What we’ve done here is defined a consistent pattern for our designers and developers to follow. We’ll always have a div container that will use a p tag to display the flash messages with a CSS class value that maps to the type of flash message that we’re displaying. This makes it easier for us to reuse the same flash message styling (and tweak if necessary), but we know that it’ll produce the same HTML across our applications.

Installing Flash Message Conductor

Like most modern Rails applications, you can install with:


script/plugin install git://github.com/planetargon/flash-message-conductor.git

Then all of our helper methods will be available to your application. We’ve also included an example CSS file, which you’ll find in the plugin directory.

Sample output:

flash message area
Uploaded with plasq’s Skitch!

Anyhow, we’ve posted the plugin up on GitHub for you all to use, if you’d like to adopt a similar approach. If you have any alternative patterns that has helped your team, do share and I’m looking forward to sharing some more of ours in the near future.

For more information, visit the Flash Message Conductor plugin on GitHub.

If anything, hopefully this will inspire those of you who find yourself copying/pasting artifacts from application-to-application to extract that code into it’s own reusable plugin. :-)

Q&A: ActiveRecord Observers and You

Posted by Sat, 28 Apr 2007 21:28:00 GMT

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[1] 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.

Related Posts

1 Don’t Repeat Yourself

Announcing the Dialogue-Driven Development Project

Posted by Tue, 03 Oct 2006 12:30:00 GMT

I woke up this morning and came across an article written by Brasten Sager, titled, Of Dialogue and Development in which he discusses his initial (and healthy) criticism of Dialogue-Driven Development.

But d3 is an evolving thing. Its earliest forms offered very little definition, leading me to believe there was little to it. As it has evolved the goals and mindset of d3 and its proponents have become a little more clear, and after further consideration I’m now convinced that my original critiques may have been wrong.

I encourage you to read his article, which offers ideas (and diagrams) on how d3 might be injected into your existing process.

A small number of interested developers have been sending us questions about d3 and were wondering what the next step was for the community. We’re working hard on outlining patterns of dialogue, which is where we plan to put of our focus into. A small group of people have joined our mailing list and IRC channel over the past few weeks, where some conversations have occurred. After reading through Brasten’s post, I believe that our IRC conversation last week was a good example of how people with different ideas about something… can come together and have a shared understanding, which is exactly what Dialogue-Driven Development is about.

Through shared understanding, we can accomplish so much more.

“In true dialogue, both sides are willing to change.” —Thich Nhat Hanh

Thanks to the hard work of Brian Ford, we now have a website to announce, which will be the portal to various conversations, patterns, and resources related to Dialogue-Driven Development.

http://www.dialogue-driven.org

Information Anxiety and Solutions

Posted by Tue, 22 Aug 2006 17:15:00 GMT

1 comment Latest by brasten Tue, 22 Aug 2006 19:10:16 GMT

Last week, Allison brought me in a copy of a book that she owns by Richard Saul Wurman. In 1976, Wurman coined the phrase, information architect. (read more)

In his book, Information Anxiety 2, Wurman discusses how we’re overwhelmed by too much information… amongst other related topics.

Allison bookmarked a page for me that discusses the problem with developing solutions without a good understanding of the problem.

“Before any solutions to any undertaking can be developed, a movement must begin to discover its beginning. Understanding the vein of the problem is the course to solving it. The best way to accomplish any endeavor is to determine its essential purpose, its most basic mission. What is the endeavor supposed to accomplish? What is the reason for embarking upon it? This is where the solution lies.”

- Richard Saul Wurman, Information Anxiety 2

Wurman then goes on to suggest, “There are two parts to solving any problem: What you want to accomplish, and how you want to do it. Even the most creative people attach issues by leaping over what they want to do and going on to how they will do it. There are many how’s but only one what.”

There are many how’s but only one what

“You must always ask the question, “What is?” before you ask the question “How to?”“

When Brian and I began rethinking how we were extracting information from our clients, it was important to understand why we felt it was necessary. We’re convinced that the more we can enhance our patterns of dialogue with our clients, the more confidence we’ll have in our approach to building solutions that provide them with that they need, not just what they think they need (want).

Next time a client brings you a list of features for their product, please be sure to ask yourself and your client, “why” the product needs them. What are these hows providing their business and user goals?

d3 not DDD

Posted by Tue, 08 Aug 2006 16:15:00 GMT

6 comments Latest by MSM Thu, 10 Aug 2006 00:40:48 GMT

First, a quick update from our sponsors…

Brian and I talked yesterday and agreed to stop referring to Dialogue-Driven Development as DDD. We’ll leave that for the Domain-Driven Design fans. From now one, the short version for Dialogue-Driven Development will be d3.

MSM posted an email in regards to d3 on a Scrum development mailing list. He writes, “While I believe there’s room for plenty of Agile methodologies in the world and wouldn’t want to discourage the development of DDD if it helps them get their software written, I would hate to see Scrum described inaccurately, especially in a well-oiled meme propagation machine like the Rails community.” (link)

Michael D. Ivey responded with, “That being said…as someone who has gotten 100% into Rails development, I find myself using Scrum less. At least, on the surface, official Scrum. Rails makes meW^WWlets me be so productive that we are basically having 1 day sprints.

What’s interesting here is that we have a someone who is working with Ruby on Rails and finds himself using Scrum less because the environment is much different. This is exactly why Brian and I started seeking out something even more lightweight. We’re not aiming to replace other methodologies, but to structure our own that focuses on dialogue. With Rails, we’re finding that the amount of collaboration and dialogue with clients has both increased and improved tremendously.

Ivey also goes on to say, “I believe, having done Scrum well, and having done the ””Rails experience,”” that what Robby and …. the other guy …. are describing with ””Dialogue Driven Development”” is exactly what happens when you start with Scrum or something Scrummy, add a hyper-productive programming language and framework, mixin a very active and interactive customer, and then just start running at a comfortable pace and see when you get somewhere cool.

Perhaps Michael is right… and of course, this is open for discussion. :-)

Brian and I are spending a good deal of time thinking and talking about this stuff. We want to outline a new pattern that changes how requirements are gathered and documented through dialogue. It’s apparent that as we read different peoples comments on our articles that the general consensus is to interpret the Product Backlog pattern described in the books on Scrum in a way that works best for your team. The approach outlined in Agile Software Development with Scrum doesn’t work for us.

What’s your pattern? Share your story…