Sonny Black
Sonny Black

Reputation: 1617

How to send unique messages daily via Action Mailer

So I have a newsletter, but I'm having trouble coming up with a way to track Quotes that have been sent. I'd like to track sent quotes to avoid sending duplicates.

The app is quite simple, there's a quote model that belongs_to category model, and a subscriber model that belongs to a category model. A category has_many subscribers and quotes.

The code below sends the first Quote to its subscriber. Of course You have to maintain a table or a field that keeps of track of what quotes were sent earlier to the subscriber so you can always manage to send a new quote every day.

Category.all.each do |category|
   category.subscribers.each do |subscriber|
      SubscriptionMailer.sendmyemail(subscriber.email, category, category.quotes.first.body, category.subscribers).deliver          
   end
end

This can further be updated to:

Category.all.each do |category|
   category.subscribers.each do |subscriber|
      SubscriptionMailer.sendmyemail(subscriber.email, category, subscriber.choose_quote(category), category.subscribers).deliver          
   end
end    

And in my subscriber.rb model I have this method ready, but not sure what code to fill it with to achieve what I want. How can I send a quote to subscribers once a day which is unique and not a duplicate of what's been sent in the past? Or maybe even an easier way would be to randomize the order, is this possible?

def choose_quote(cat)
  # send quote which is unique 
  # Meaning which was not sent 
end

Upvotes: 0

Views: 250

Answers (1)

Rubyrider
Rubyrider

Reputation: 3587

  • Your are sending quotes to your subscribers
  • You need to track which quotes has been sent to your user.

I would suggest a possible solution design for that specific problem you mentioned.

rails generate model quote_history subscriber:references quote:references # assumed there
#is a model subscriber and quote

So now subscriber_quote_history will belongs to subscribers and quotes as well.

class QuoteHistory < ActiveRecord::Base
  belongs_to :subscriber
  belongs_to :quote
  validates :quote_id, :uniqueness => {scope: :subscriber_id}
end

So both subscriber, quote should have many quote_histories has they have been sent.

class Subscriber < ActiveRecord::Base
   has_many :quote_histories
   .....
end

class Quote < ActiveRecord::Base
   has_many :quote_histories
   scope :uniq_quote_for, Proc.new {|subscriber_id| includes(:quote_histories).where.not(quote_history: {subscriber_id: subscriber_id})}
   .....
end

Now I would suggest you to write some condition in your desired method:

class Subscriber < ActiveRecord::Base
 def choose_quote(cat)
   quote = cat.quotes.uniq_quote_for(self.id).order("RANDOM()").first #Add a new history after that for that. here you will decide your own business logic.
   return quote if self.quote_histories.create(qoute_id: quote.id)
   return nil
 end
end

In your mailer do something similar:

Category.all.each do |category|
   category.subscribers.each do |subscriber|
      quote = subscriber.choose_quote(category)
      if quote  # if quote found then send email
       SubscriptionMailer.sendmyemail(subscriber.email, category, quote, category.subscribers).deliver    
      else
        next # if no quote found then go to next loop.
      end      
   end
end  

I believe this will help you to design your solution. Please note, I wrote here everything from visualization and from my own logic. Please skip some unwanted conventional errors or anything. My intention here is to just show you the way to sort your problem.

Thanks.

Upvotes: 7

Related Questions