“...I've been working since 2008 with Ruby / Ruby on Rails, love a bit of Elixir / Phoenix and learning Rust. I also poke through other people's code and make PRs for OpenSource Ruby projects that sometimes make it. Currently working for InPay...”

Rob Lacey
Senior Software Engineer, UK

ActionMailer with ActiveRecord validation

I wanted to be able to send out a mail from a controller but also validate the incoming args in a clean way. Like so…

class MessagesController < ActionController::Base

def deliver
  @message = Message.build(params[:message])
  if @message.deliver
    redirect_to home_path
  else
    render :action
  end
end

ActionMailer::Base hides the initialize methods in method_missing and most of the time you are calling ActionMailer::Base.deliver_mymail(args). This allows you to specify all of the standard actionmailer settings in Message.build and return a Message object.

class Message < ActionMailer::Base

  include Validatable
  validates_presence_of :from, :body

  def self.build(args = {})
    new('default', args)
  end

  def self.action_mailer_methods
    return [
      :bcc,
      :body,
      :cc,
      :charset,
      :content_type,
      :from,
      :reply_to,
      :headers,
      :implicit_parts_order,
      :mime_version,
      :recipients,
      :sent_on,
      :subject,
      :template
    ]
  end

  def default(args)
    new_args = args.clone
    new_args.each do |k,v|
      if self.class.action_mailer_methods.include?(k)
        send(k, new_args.delete(k))
      end
    end

    if body.kind_of?(Hash)
      @body.merge!(new_args)
    end

  end

  def deliver
    if self.valid?
      return deliver!
    else
      return false
    end
  end

end
GPK of the Day Bad Breath SETH