Last active
August 29, 2015 14:20
-
-
Save soulcutter/88b84dbda99a44ed02d3 to your computer and use it in GitHub Desktop.
Toggling interest groups in list subscriptions in MailChimp's v2.0 API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "active_support/core_ext" | |
require "delegate" | |
require "mailchimp" | |
require "singleton" | |
class MailingList::MailChimp | |
attr_reader :user, :member_info | |
def initialize(user, member_fetcher = member_info_api) | |
@user = user | |
@member_info = member_fetcher | |
@mailchimp = nil # lazily instantiated | |
end | |
def subscribed_to?(list) | |
member_info[list]["status"] == "subscribed" | |
end | |
def interested_in?(list:, grouping:, group:) | |
!!member_info[list]["merges"]["GROUPINGS"] | |
.find { |x| grouping.match x["name"] }["groups"] | |
.find { |x| group.match x["name"] }["interested"].presence | |
end | |
def subscribe_to(list, interest_groups: {}) | |
# returns something like: {"email"=>"[email protected]", "euid"=>"5a9245aad2", "leid"=>"35566593"} | |
mailchimp.lists.subscribe( | |
list_id(list), | |
{ "email" => user.email }, | |
merge_vars(list, interest_groups), | |
"html", | |
send_double_optin_message = false, | |
update_existing_subscriber = true, | |
replace_interest_groups = true, | |
send_welcome_email = true, | |
) | |
rescue Mailchimp::ListAlreadySubscribedError => e | |
# this should not happen because `update_existing_subscriber = true` | |
# but just in case... do nothing | |
rescue Mailchimp::ListInvalidInterestGroupError => e | |
NewRelic::Agent.notice_error e | |
Rails.logger.tagged("Mailchimp API") { |logger| logger.warn e } | |
ensure | |
invalidate_cache(list) | |
end | |
def unsubscribe_to(list) | |
# returns something like: {"complete"=>true} | |
mailchimp.lists.unsubscribe( | |
list_id(list), | |
{ "email" => user.email }, | |
completely_delete_member = true, | |
send_goodbye_email = true, | |
send_unsubscribe_notice = true | |
) | |
rescue Mailchimp::EmailNotExistsError | |
# do nothing | |
ensure | |
invalidate_cache(list) | |
end | |
def merge_vars(list, interest_groups) | |
{ | |
"FNAME" => user.first_name, | |
"LNAME" => user.last_name, | |
"groupings" => groupings_with(interest_groups, list: list) | |
}.tap do |hash| | |
Rails.logger.tagged("mailchimp", "MERGE VARS") { |log| log.debug hash.inspect } | |
end | |
end | |
def groupings_with(interest_groups, list: ) | |
interest_groups = Hash(interest_groups) | |
groupings = member_info[list]["merges"]["GROUPINGS"].presence | |
groupings = flatten_interests(Array(groupings)) | |
merge_groupings(groupings, interest_groups) | |
end | |
private | |
def mailchimp | |
@mailchimp ||= Mailchimp::API.new(Settings.mailchimp.api_key) | |
end | |
def member_info_api | |
Hash.new do |h, list| | |
response = mailchimp.lists.member_info(list_id(list), [{ email: user.email }]) | |
response = SafeResponse.new(response) | |
h[list] = response["data"].first | |
end | |
end | |
def list_id(list) | |
Settings["mailchimp"].try(:[], "lists").try(:[], list.to_s) | |
end | |
def invalidate_cache(list) | |
member_info.delete(list) | |
end | |
def flatten_interests(groupings) | |
groupings.each_with_object([]) do |grouping, new_groupings| | |
active_interests = groups = [] | |
Array(grouping["groups"]).each do |group| | |
active_interests << group["name"] if group["interested"] | |
end | |
new_groupings << { "name" => grouping["name"], "groups" => groups } | |
end | |
end | |
def merge_groupings(groupings, interest_groups) | |
interest_groups.each do |group, interests| | |
grouping = groupings.find { |x| x["name"] == group } | |
if grouping.nil? | |
grouping = { "name" => group, "groups" => [] } | |
groupings << grouping | |
end | |
interests.each do |interest_hash| | |
interest_name = interest_hash["name"] | |
is_interested = interest_hash["interested"] | |
if is_interested | |
grouping["groups"] << interest_name | |
else | |
grouping["groups"].delete(interest_name) | |
end | |
end | |
grouping["groups"].uniq! | |
end | |
groupings | |
end | |
class SafeResponse < SimpleDelegator | |
def self.safe_delegate(*methods) | |
methods.each do |method| | |
define_method(method, ->(*args, &block) { | |
value = __getobj__.send(method, *args, &block) | |
value.nil? ? BlackHole.instance : SafeResponse.new(value) | |
}) | |
end | |
end | |
safe_delegate :[] | |
safe_delegate :detect, :find, :first, :select | |
end | |
class BlackHole | |
include Singleton | |
def itself; self end # TODO remove when upgrading to Ruby 2.2+ | |
[:detect, :find, :first, :select].each do |method| | |
alias_method method, :itself | |
end | |
def [](*); self end | |
def blank?; true end | |
def empty?; true end | |
def presence; nil end | |
def present?; false end | |
def nil?; true end | |
end | |
end | |
# user must have #email #first_name and #last_name for everything to work | |
list = MailingList::MailChimp.new(user) | |
list.subscribe_to(:mailing_list, { "grouping name" => [{ "name" => "group name", "interested" => true}] | |
list.interested_in? :mailing_list, grouping: "grouping name", group: "group name" # => true | |
list.subscribe_to(:mailing_list, { "grouping name" => [{ "name" => "group name", "interested" => false}] | |
list.interested_in? :mailing_list, grouping: "grouping name", group: "group name" # => false | |
list.unsubscribe_to :mailing_list |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment