开发者

Advice on how to send email to multiple users based on an association

I have created a Ruby on Rails application where users can track workouts. The can do so either privately or publicly. On workouts which are public ( workout.share == 1 ) I allow users to comment. When a comment is created on a workout, the workout owner is notified via email. That all works great.

I am now looking for some advice on the best way to allow users who have commented on a workout, to also be notified via email. Here is an example.开发者_StackOverflow

User A creates Workout 1. User B comments on Workout 1 and User A receives an email notification. User C also comments on Workout 1 and both User A and User B receive email notifications.

What is the best way to tell my application to loop through all the users who have commented on Workout 1 and send an email to them?

Currently I am sending an email to the workout owner with the following code in the comments_controller (I realize this could be cleaner code):

class CommentsController < ApplicationController

...


def create
     @workout = Workout.find(params[:workout_id])
     @comment = @workout.comments.build(params[:comment])
     @comment.user = current_user

     respond_to do |format|
       if @comment.save
         if @comment.workout.email_notification == 1
          @comment.deliver_comment_notification_mail!
          format.html { redirect_to( projects_path) }
          format.js
        else
          format.html { redirect_to( projects_path) }
          format.js
        end
      else
      end
    end
  end

...

and in comment_mailer.rb

def comment_notification_mail(comment)

     subject       "Someone commented on your Workout"
     recipients("#{comment.workout.user.username} <#{comment.workout.user.email}>")
     from("foobar")
     body         :comment => comment,
                  :commenter => comment.user,
                  :workout => comment.workout,
                  :commentee => comment.workout.user,
                  :workout_url => workout_url(comment.workout),
                  :commenter_url => user_url(comment.user)


   end


To find out a workout owner and commenter is not a hard job. My suggestions are:

  1. move the code of sending email in your controller to your model, using #after_create, eg:

    class Comment < ActiveRecord::Base
      #...
      after_create :notify_subscribers
    
    
      def subscribers
        (self.workout.commenters << self.workout.owner).uniq
      end
    
    
      def notify_subscribers
        #... implemented below
      end
    end
    
  2. using delayed_job or other tools to put the email sending job to background, or the request would be blocked until all the emails has been sent. eg, in the #notify_owner_and_commenter method

    def notify_subscribers
      self.subscribers.each do |user|
        CommentMailer.send_later :deliver_comment_notification_mail!(self, user)
      end
    end
    

    Then you need to refactor you #deliver_comment_notification_mail! method with two arguments.

Delayed job ref: https://github.com/tobi/delayed_job


From my POV, it's all the work of the mailer. I'd just rewrite the comment_notification_mail to something more neutral (which could speak to workout owner and commenters).

Then something like:

def comment_notification_mail(comment)

 recs = [comment.workout.user]
 recs << comment.workout.comments(&:user)
 recs -= comment.user

 subject  "Someone commented on your Workout"
 recipients(recs.inject('') { |acc, r| "#{r.username} <#{r.email}>" })
 from("foobar")
 body     :comment => comment,
          :commenter => comment.user,
          :workout => comment.workout,
          :commentee => comment.workout.user,
          :workout_url => workout_url(comment.workout),
          :commenter_url => user_url(comment.user)
end

Of course, if mails are not supposed to be public, send by bcc ;)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜