title: Action Mailer Invites Rails 3.1
body: <p>Using Ryan Bate's RailsCasts #124 Beta Invites (as well as the updated rails 3.1 api) as a crutch, I'm trying to put together my first piece of Action Mailer functionality: inviting someone to collaborate with you on a project. </p>
  
  <p>My issue is that the <code>:recipient_email</code> isn't getting saved in the DB and I can't see what I'm missing.</p>
  
  <p>config/initializers/setup_mail.rb</p>
  
  <pre><code>ActionMailer::Base.smtp_settings = {
    :address                    =&gt; "smtp.gmail.com",
    :port                       =&gt; 587,
    :domain                     =&gt; 'blah.com',
    :user_name                  =&gt; 'gmail username',
    :password                   =&gt; 'gmail password',
    :authentication             =&gt; 'plain',
    :enable_starttls_auto       =&gt; true
  }
  
  ActionMailer::Base.register_interceptor(DevelopmentMailInterceptor) if Rails.env.development?
  </code></pre>
  
  <p>app/models/invitation.rb</p>
  
  <pre><code>class Invitation &lt; ActiveRecord::Base
  
    email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  
    attr_accessor :recipient_email
  
    belongs_to :sender, :class_name =&gt; "User", :foreign_key =&gt; "sender_id"
    has_one :recipient, :class_name =&gt; "User", :foreign_key =&gt; "recipient_id"
  
    validates_presence_of :recipient_email, :on =&gt; :create, :message =&gt; "can't be blank"
    validates :recipient_email, :format =&gt; email_regex
    validate :recipient_is_not_registered
  
    before_create :generate_token
  
    def sender_name
      sender.user_name
    end
  
    def sender_email
      sender.email
    end
  
    private
  
      def recipient_is_not_registered 
        exsisting_user = User.find_by_email(recipient_email)
        if exsisting_user
          errors.add :recipient_email, 'is already a member.'
        else
          recipient_email
        end
      end
  
      def generate_token
        self.token = Digest::SHA1::hexdigest([Time.now, rand].join)
      end
  
  end
  </code></pre>
  
  <p>app/models/user.rb (minus all the auth stuff)</p>
  
  <pre><code>class User &lt; ActiveRecord::Base
    attr_accessible :invitation_token
  
    has_many :sent_invitations, :class_name =&gt; "Invitation", :foreign_key =&gt; "sender_id" 
    belongs_to :invitation
  
  end
  </code></pre>
  
  <p>app/controller/invitations_controller.rb</p>
  
  <pre><code>class InvitationsController &lt; ApplicationController
    before_filter :authenticate
  
    def new
      @title = "Invite client"
      @invitation = current_user.sent_invitations.new
    end
  
    def create
      @invitation = current_user.sent_invitations.create!(params[:invitation])
      sender_name = @invitation.sender_name
      sender_email = @invitation.sender_email
      if @invitation.save
        Mailer.invitation(@invitation, signup_url(@invitation.token), sender_name, sender_email).deliver
        flash[:success] = "Your client has been sent the email. Why not create a booking for them?"
        redirect_to bookings_path
      else
        @title = "Invite client"
        render :new
      end
    end
  
  end
  </code></pre>
  
  <p>app/mailers/mailer.rb</p>
  
  <pre><code>  def invitation(invitation, signup_url, sender_name, sender_email)
      @signup_url = signup_url
      @sender_name = sender_name
      @sender_email = sender_email
      mail(:to =&gt; invitation.recipient_email, 
           :subject =&gt; "Invitation to Join",
           :from =&gt; @sender_email)
    end  
  </code></pre>
  
  <p>app/views/invitations/_invitation_form.html.erb</p>
  
  <pre><code>&lt;%= form_for @invitation do |f| %&gt;
      &lt;%= render 'shared/error_messages', :object =&gt; f.object %&gt;
      &lt;%= f.hidden_field :email_token %&gt;
      &lt;br /&gt;
      &lt;div class="field"&gt;
          &lt;%= f.label :recipient_email, "Client's email address" %&gt;
          &lt;%= f.email_field :recipient_email %&gt;
      &lt;/div&gt;
      &lt;br /&gt;
      &lt;div class="action"&gt;
          &lt;%= f.submit "Send invitation", :class =&gt; "a small white button radius" %&gt;
      &lt;/div&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p>The SQL log showing that the :recipient_email isn't getting saved</p>
  
  <pre><code>Started POST "/invitations" for 127.0.0.1 at 2011-12-14 21:27:11 +1100
    Processing by InvitationsController#create as HTML
    Parameters: {"utf8"=&gt;"✓", "authenticity_token"=&gt;"7/SGZypGXtf9ShlcjC6o8ZRj2Qe4OJTHdjis2/m3ulc=", "invitation"=&gt;{"recipient_email"=&gt;"users@email.com"}, "commit"=&gt;"Send invitation"}
    User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
     (0.1ms)  BEGIN
    User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."email" = 'users@email.com' LIMIT 1
    SQL (0.4ms)  INSERT INTO "invitations" ("created_at", "recipient_email", "sender_id", "sent_at", "token", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["created_at", Wed, 14 Dec 2011 10:27:11 UTC +00:00], ["recipient_email", nil], ["sender_id", 1], ["sent_at", nil], ["token", "56fba1647d40b53090dd49964bfdf060228ecb2d"], ["updated_at", Wed, 14 Dec 2011 10:27:11 UTC +00:00]]
     (10.2ms)  COMMIT
    User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
     (0.1ms)  BEGIN
    User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."email" = 'users@email.com' LIMIT 1
     (0.1ms)  COMMIT
  Rendered mailer/invitation.text.erb (0.4ms)
  
  Sent mail to users@email.com (7ms)
  Date: Wed, 14 Dec 2011 21:27:11 +1100
  From: admin@email.com
  </code></pre>