Friday, January 28, 2011

ActionMailer 3 - why do you call instance methods as class/self methods?

I didn't even notice this little trick! As long as I didn't have to call deliver_welcome_message (or deliver_*) methods that would magically call welcome_message, I was happy that now the magic is gone. Things are transparent!
Here's an example showing the change: Say you have the following mailer:
class Notifier < ActionMailer::Base
  def welcome_message(new_user)
    #a warm welcome message
  end
end
Now, prior to Rails 3, or ActionMailer 3, you would write the following to actually call this method to get the benefits of ActionMailer magics, such as finding the view based on method name and so on:
Notifier.deliver_welcome_message(new_user_instance)  
I am sure this deliver_* was a clever design decision to solve a hard problem, that is, finding the view name based on the method name. However, in ActionMailer 3, this is gone. Now the question is, if this trick is gone, how come it still finds the view name from the method name? Who sets the view name? To know the answer, first, let's take a look at how we call the welcome_message now.
Notifier.welcome_message(new_user_instance).send
Instead of

Notifier.new.welcome_message(new_user_instance).send

So, the magic deliver_ prefix is gone. But, did you see the new trick? Well, its a clever design again. The trick this time is, you call your instance method, welcome_message as if it was a class method. But there is no class method called welcome_message, so it instead goes to method_missing and thats how it sets up the view name from this call. Here's the code that does this little trick!
def method_missing(method, *args) #:nodoc:
    return super unless respond_to?(method)
    new(method, *args).message
  end
All it does is, instantiates the mailer with the method name!

However, this design decision has interesting side effects as well. Or may be not side effects, but rather core effects. For example, since you are calling your mailer methods as class methods, you cannot use a single mailer instance to send out multiple emails at the same time. In fact, every mailer has only one instance of message. So, it cannot store two messages at the same time. This is as if, you can have multiple methods in a class, but you cannot call more than one class or you will mess up the class's state!

Wonder why? Well, this is rooted in another key design choice: ActionMailer::Base is a subclass of AbstractController::Base. Now, if you look at controllers, you will notice that at any given point of time, a controller instance is only responsible for responding to a single action. This is logical for controllers. But how about mailers? I see a mismatch in my mental model and the actual implementation model. I don't see a reason why a mailer is a controller! For the sake of code reuse? But that could be done via delegation anyway.

I will end this post with one question:
Do you think mailer is a controller? hints: think about LSP.

Friday, January 14, 2011

Social Helpers in ASP.Net MVC3 (Facebook, Twitter, Gravatar etc.)

This site shows the examples!
http://www.asp.net/webmatrix/tutorials/13-adding-social-networking-to-your-web-site

Now, the social links and buttons are no longer from a third-party source, its straight from Microsoft. I don't know if this is first-party or second-party :p

Thursday, January 13, 2011

My Article at CodeProject: MvcMailer

I just released a .Net NuGet package called MvcMailer and to get people super easily started, put an article at CodeProject.com. You are most welcome to the article at http://www.codeproject.com/KB/aspnet/MvcMailerNuGet.aspx
I welcome your comments and suggestions!

Friday, January 07, 2011

C# Named Parameters Can be Very Useful

Think about the following code example:
htmlHelper.InputHelper(InputType.CheckBox, name, "true", true /* useViewData */, false /* isChecked */, true /* setId */, false /* isExplicitValue */, htmlAttributes);
This line is taken from the source code of ASP.NET MVC, or to be more specific its a line from the InputExtension class. I think the intent of the original developer is clear:
Add comment next to arguments so that one can easily read the method call without getting lost in a who's who since there are quite some arguments to pass.
To learn more about named parameters using C#, you can visit this post by ScottGu.

Sunday, January 02, 2011

2011: Yet Another New Year

Dear Readers:
Happy 2011. 2010 was a great year. Why?

  • Defended my MSc thesis after a moderate 16 months of grad school life.
  • Published 3 papers in 3 international conferences.
  • Visited 4 new countries - Netherlands, Sweden, Finland and Norway.
  • Visited a few interesting cities - Vancouver, Victoria, Edmonton.
  • 100+ posts on DrinkRails.com.
  • 25,000+ visits to my two blogs from all over the world.
  • Developed a fresh new app, Plexina Central, for Wairever Inc.
  • Lived a healthy life.
  • Bought my first (98 Corolla) and second (2000 CR-V) cars (also sold my first car)!
To live up to this standard, 2011 is surely challenged by 2010. Let's see how 2011 rolls: To give you a heads up, I am joining ThoughtWorks as a Consultant on January 4th!
However, 2010 was the only year in my life when I didn't see my parents and siblings. I hope, 2011 does a better job in this regard. It is getting essential now.
This is how I look at the close of 2010
And I want to look leaner at the close of 2011 or even before that :(