tags:

views:

102

answers:

4

Hi, what the syntax is in Action Mailer Basics rails guide ?

class UserMailer < ActionMailer::Base
   def welcome_email(user)
      recipients    user.email
      from          "My Awesome Site Notifications <[email protected]>"
      subject       "Welcome to My Awesome Site"
      sent_on       Time.now
      body          {:user => user, :url => "http://example.com/login"}
   end
end

How should i understand the construction, like

from "Some text for this field"

Is it an assignment the value to a variable, called "from" ?

+11  A: 

No, it's a method call. The name of the method is from, and the argument is a string. In Ruby, parentheses around method calls are optional, so

from "Some text for this field"

is the same as

from("Some text for this field")

Rails (and many Ruby libraries) like to express code in a natural language style, though, so the parentheses-less version reads better, hence why it is used in examples.

mipadi
+2  A: 

It is a call to a method from with the argument "Some text for this field"

The method comes from the ActionMailer::Base class that your UserMailer extends from.

In Ruby the parentheses around a method call are optional unless something would be ambiguous so the statement is equivalent to from("Some text for this field")

Rails has a coding style that prefers to be close to natural language where possible, hence not using parentheses unless necessary.

Calling this method sets an instance variable @from to the value you provide so that it can be used later when sending the message.

Normally when you have accessor methods for getting and setting a variable you would have from= to set the value and from to return the value, however ActionMailer uses something called adv_attr_accessor to define the from method so that if you call it with a parameter then it acts as a setter but if you call it with no parameters then it acts as a getter.

This can be seen in actionmailer-2.x.x/lib/action_mailer/base.rb and actionmailer-2.x.x/lib/action_mailer/adv_attr_accessor.rb

mikej
A: 

You could also call from an attribute. It's a property of the email, but how it's implemented is hidden from you (encapsulation). This is a Good Thing. It means that if Rails core decided it's better to change @from into several variables, you wouldn't need to change any of your code.

Andrew Grimm
A: 

It's not an assignment. In Ruby, assignments are done using the assignment operator = like this:

var = val

You are probably thinking of some Lisp dialects where assignment looks like this:

(def var val)

It's just a simple receiverless message send.

In Ruby, the general syntax for a message send is

receiver.selector(argument1, argument2)

However, if the receiver is self, you can leave off the receiver, so

selector(argument1, argument2)

is the same as

self.selector(argument1, argument2)

[Note: this is not quite true. In Ruby, private methods can only be invoked via a receiverless message send, so if in this example self responds to the selector message by invoking a private method, only the first variant will work, the second will raise a NoMethodError exception.]

Also, in cases where there are no ambiguities, you can leave off the parentheses around the arguments like this:

receiver.selector argument1, argument2

If you put the two things together, you can now see that

selector argument1, argument2

is equivalent to

self.selector(argument1, argument2)

and thus

from "Some text for this field"

is equivalent to

self.from("Some text for this field")

There is a third shortcut in Ruby's message sending syntax: if the very last argument to a message send is a Hash literal, then you can leave out the curly braces. So, the last line in the above example could also be written as

  body          :user => user, :url => "http://example.com/login"

Also, in Ruby 1.9, a Hash literal where all keys are Symbols can be written using an alternative Hash literal syntax:

 { key1: val1, key2: val2 }

is the same as the old syntax

{ :key1 => val1, :key2 => val2 }

which means that, at least in Ruby 1.9, that last line could also be written as

  body          user: user, url: "http://example.com/login"
Jörg W Mittag