User email preferences - thinking of using rails-settings gem. Am I doing this right?

443 Views Asked by At

Question

I want to implement email preferences for my users. I think that either the rails-settings gem or its rails-settings-cached fork is the way to go, but I'm not quite sure. Should I use the rails-settings (or rails-settings-cached) gem to do this, or is there a better way? If I should use one of these gems, any tips or potential gotchas are greatly appreciated.

What I want to do

  1. A master switch - all system emails on or off

    Each user has a "master switch" that tells me whether they've opted out of all emails. It would basically be a checkbox that says "Send me emails". If the box is unchecked (false), they never get system emails (except password resets). If the box is checked (true), they're eligible to get system emails.

  2. Opt in/out for several system emails

    If the master switch is "true" (eligible for emails), the next of configuration is that I offer checkboxes for individual system emails ("New message received", "New comment on thread I started"). They can opt into or out of each system email.

  3. Opt in/out for some emails with additional delivery options

    Finally, some emails will be "summary" emails, and I'll want to know if the user is eligible to receive the email and how often they want to receive it. For example, a daily summary of account activity. I want to allow them to opt in/out of the email, and to tell me which weekdays to send the summary if they opt in. So "Yes, send me this email Monday through Friday." Or a weekly summary email: "Yes, send me this email every Sunday."

If I understand the rails-settings gem, then my User model would look something like this:

class User < ActiveRecord::Base
  has_settings do |s|
    s.key :email_master, :default => true
    s.key :new_comment_email,  :default => true
    s.key :daily_recap_email,  :defaults => { :send => true, :days => [0,1,2,3,4,5,6] }
    # or maybe this would be easier
    s.key :daily_recap_email,  :defaults => { :send => true, :sunday => true, :monday => true, :tuesday => true }
    s.key :weekly_recap_email,  :defaults => { :send => true, :day => 0 }
  end
end

Then, I could say something like:

if user.settings.email_master && user.settings.new_comment_email
  UserMailer.new_comment_email(user).deliver
end

Or, a more complicated case for the daily_recap email:

if user.settings.email_master && user.settings(:daily_recap_email).send && user.settings(:daily_recap_email).days.include?(3)
  UserMailer.daily_recap_email(user).deliver
end

What I did for this in a previous app

Previously, I have done this with an EmailPreferences model that is 1-to-1 with my Users model. The issue was that scaling it was tough - any time I created a new system email based on some event, I had to add a column to my EmailPreferences table. It was also tricky because the table was mostly booleans, so I could have a "in" or "out" (true or false) setting, but not much more. I also found it pretty difficult to figure out whether a user should get an email because I had to chain methods to get to the ultimate question, "Should I send this email to this user as a result of this event?"

0

There are 0 best solutions below