Reputation: 1617
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
Reputation: 3587
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