Coder Social home page Coder Social logo

active_mailer's Introduction

ActiveMailer

Email needs to have somewhere to put the business logic surrounding it, and the controller is not the place for that.

See the disagreement:

Installation

  1. Add gem "active_mailer" to your Gemfile and run bundle install

  2. Run rails generate active_mailer:install

  3. Run rake db:migrate

Basic Usage

There's only a partial generator. In the mean time, making a new ActiveMailer class can be done like this.

  1. Run rails generate model FooEmail --no-migration --parent ActiveMailer::Base, you can pass any additional columns just like you would for a normal generate model.

  2. Run rails generate active_mailer:migration FooEmail

  3. Make the template for your email (in this case called foo_email.rb) in app/views/active_mailer/base/default_action_mailer/foo_email.html.erb

You're ready! You can send your email by making an instance of FooEmail, setting the appropriate details, and calling send!.

> f = FooEmail.new(:subject => "My Awesome Email", :sender => "[email protected]",
>                  :recipients => "[email protected]")
=> #<FooEmail id: nil, blahblahblah>

> f.send!
=> true

Advanced Usage

If your email is always going to have the same subject, sender, bcc, etc, then you can set those in the ActiveMailer object. Remember that it's really just an ActiveRecord object, so you can do anything in this class you can do in ActiveRecord.

Here's an example of using ActiveRecord associations to make sure there's a user for the email. It also includes setting the subject and sender by default.

class BeerEmail < ActiveMailer::Base
  belongs_to :user

  validates_presence_of :user

  def after_initialize
    self.subject = "It's Beer O'Clock"
    self.sender  = "[email protected]"
  end
end

Contributing

Setup the project with script/setup.

We use the Appraisal gem to test against multiple versions of Rails. By default rake will test every supported version of Rails, but you can isolate a specific vesion by using appraisal rails4.1 rake.

The tests use a micro Rails app that you should know about.

Bugs/Feature

Authors

  • Matt Gordon
  • Elijah Miller

Copyright (c) 2009-2015 Expected Behavior, LLC, released under the MIT license

active_mailer's People

Contributors

esquivalient avatar janxious avatar jason-o-matic avatar jqr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

active_mailer's Issues

View path should be app/views/emails

While there's nothing technically wrong with app/views/active_mailer/base/default_action_mailer/ it's not an intuitive, doesn't conform to reasonable expectations, and a bit tedious to access a path that deep. ActiveMailer views should be at app/views/emails by default.

It should be possible to iteratively add recipients to an email

(rdbg) itme.recipients << "[email protected]"    # ruby
eval error: EmailUser(#17760) expected, got "[email protected]" which is an instance of String(#3440)
  /Users/esquivalient/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activerecord-7.0.3.1/lib/active_record/associations/association.rb:299:in `raise_on_type_mismatch!'
  /Users/esquivalient/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activerecord-7.0.3.1/lib/active_record/associations/has_many_through_association.rb:17:in `block in concat'
  /Users/esquivalient/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activerecord-7.0.3.1/lib/active_record/associations/has_many_through_association.rb:16:in `each'
  /Users/esquivalient/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activerecord-7.0.3.1/lib/active_record/associations/has_many_through_association.rb:16:in `concat'
  /Users/esquivalient/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activerecord-7.0.3.1/lib/active_record/associations/collection_proxy.rb:1032:in `<<'
  (rdbg)//Users/esquivalient/Dropbox/code/burndown/test/models/invite_team_member_email_test.rb:1:in `block in <class:InviteTeamMemberEmailTest>'
nil

doesn't work, but

(rdbg) itme.recipients = ["[email protected]"]    # ruby
[#<ActiveMailer::EmailUser:0x000000010efb6558
  id: 9,
  email_address: "[email protected]",
  created_at: Thu, 04 Aug 2022 19:34:23.486894000 UTC +00:00,
  updated_at: Thu, 04 Aug 2022 19:34:23.486894000 UTC +00:00>]
(rdbg)

does. That's a needless paper cut.

Set up CI

It's easier to have more collaborators if the tests are run automatically and the results can be seen from the PR.

Complete the generator

From here:

There's only a partial generator. In the mean time, making a new ActiveMailer class can be done like this.

Generated migration should specify the ActiveRecord release

The migration generator for ActiveMailer doesn't include the ActiveRecord version number, which causes this error when the migration is executed

StandardError: Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Active Record release the migration was written for:

  class CreateInviteTeamMemberEmails < ActiveRecord::Migration[7.0]
/path/to/rails_root/db/migrate/20220804162528_create_invite_team_member_emails.rb:1:in `<main>'

The generator should include the current ActiveRecord number for the project when creating the ActiveMailer migration.

Generated models should include comments explaining the various options

ActiveMailer can do a lot. It would be more convenient for users if the newly generated model included comments and commented code demonstrating common use cases like

  • setting defaults like subject/sender
  • setting variables to pass to the view
  • setting a layout
  • validating an email is correct before sending
  • storing information about the sent email for auditing

Generated migration should not include columns automatically created by create_active_mailer_table

create_active_mailer_table automatically makes

    # t.integer   :sender_id
     # t.timestamp :sent_at
     # t.string    :subject

and they're also included in the generated migration. That results in errors like

you can't define an already defined column 'sent_at'.
/Users/esquivalient/Dropbox/code/burndown/db/migrate/20220804162528_create_invite_team_member_emails.rb:8:in `block in change'
/Users/esquivalient/Dropbox/code/burndown/db/migrate/20220804162528_create_invite_team_member_emails.rb:3:in `change'

Validation to prevent sending emails that have no recipients should have a better error message

Make an ActiveMailer email with subject and sender, but no recipient, and send! it. You'll see

Error:
InviteTeamMemberEmailTest#test_can_send_valid_invitation_email:
ArgumentError: SMTP To address may not be blank: []
    test/models/invite_team_member_email_test.rb:7:in `block in <class:InviteTeamMemberEmailTest>'

instead of the nice message from ActiveMailer::Base that should like like "You have to have at least one recipient in the to, cc, or bcc fields" from this code

  validate :must_have_at_least_one_recipient_of_some_kind

   def must_have_at_least_one_recipient_of_some_kind
     if self.recipients.blank? and self.cc.blank? and self.bcc.blank?
       self.errors[:base] << "You have to have at least one recipient in the to, cc, or bcc fields"
     end
   end

I think this is because the Rails errors interface has changed and ActiveMailer needs to be updated to add errors the correct way. I think something like this

class Comment
  include ActiveModel::Validations

  validate do |comment|
    comment.must_be_friends
  end

  def must_be_friends
    errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
  end
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.