Mailchimp does not forget about unsubscribed users - ruby-on-rails

I'm having a problem when it comes to unsubrscibe email from my mailchimp list.
Basically I have a user with an email. When the user subscribe to my service I automatically insert his email into my mailchimp list through the gem gibbon (the server is Ruby on Rails v2.2.3)
##gibbon = Gibbon::Request.new(api_key: ENV['MAILCHIMP_API_KEY'])
##list = 'list_id'
...
##gibbon.lists(##list).members.create(body: {email_address: email, status: "subscribed", merge_fields: {FNAME: first_name, LNAME: full_name}})
After creating the account the user can obviously change his email address. If he does so, I add the new email to the mailchimp list and I delete the old one:
begin
##gibbon.lists(##list).members.create(body: {email_address: email, status: "subscribed", merge_fields: {FNAME: first_name, LNAME: full_name}})
rescue => e
render :json => {
:error => true,
:message => "Email already present",
:user => u,
:personal_link => u.current_link
}
return
end
member = ##mailchimp.lists(##list).members(u.email)
member.update status: "unsubscribed"
This works fine in most cases.
The problem comes when I try to change my email with my old one:
0) Subscribe to the website with the email "test#gmail.com"
Works fine.
1) From my account I change my email from "test#gmail.com" to "test1#gmail.com"
Works fine, I don't see anymore my old email in the mailchimp list and I see the new one.
2) Change back my email from "test1#gmail.com" to "test#gmail.com"
Mailchimp throws this error:
#<Gibbon::MailChimpError: the server responded with status 400 #title="Member Exists", #detail="test#gmail.com is already a list member.
The problem is that I don't have any user with this email in the database and I don' have any user with that email in my mailchimp list.
It' like mailchimp does not forget about unsubribed user and prevents me to add the same user twice in a list, even if it has been cancelled before.
How can I solve the problem?

I solved the problem. Basically for mailchimp a "unsubscribed" user is not a deleted user, so you can subscribe two users with the same email even if their state is different.
Instead of changing their status to "unsubscribed" I deleted them:
email_hash = Digest::MD5.hexdigest(u.email).downcase
##gibbon.lists(##list).members(email_hash).delete

Related

How can I verify username or email are correct using Devise and Rails 4

I am using Devise and Rails 4.
I am working with login screen. In login screen i'm passing username/email and password but I have to check whether any one of the field username or email matched with any user in system.
Tried following condition to find user with username or email but it will be throwing an error for devise valid password method.
Condition:
user = User.where(["username = :value OR email = :value", { :value => username.downcase }])
after this i'm checking user password as like user.valid_password?(password)
Error: NoMethodError (undefined method `valid_password?' for #)
For following condition valid_password? will be working fine
user = User.find_by(email: email.downcase)
But i have to check both username and password in ::find_by method like as follows
user = User.find_by("email= email.downcase OR username= email.downcase")
Is there some way I can accomplish something like above?
This is most wise confuse error, when an single instance is mixed up wish a relation, you simply forgot #first select from the relation, since where returns relation, rather than find_by, which returns a record for single match. So just rewrite (for rails 5):
user = User.where(email: email.downcase).or(username: email.downcase).first
and for Rails 4 with arel:
users = User.arel_table
user = User.where(users[:email].eq(downcase).or(users[:username].eq(email.downcase))).first
or with partially plain SQL:
user = User.where(["username = :value OR email = :value", { :value => username.downcase }]).first

Send bulk Email with mailchimp

I need to send promotional email and fetch there corresponding stats.Currently i am using Gibbon Gem but not able to create campaign through .Is there any way to create campaign and add bulk email in receiver
through Gibbon Gem or there is any other Gem to work for same.I need all stat of a campaign like sent ,bounced, effective email.Which version Of Gibbon Gem should i use to create campaign and contact list through Api
Gibbon does allow you to create and trigger campaigns through the Mailchimp API v3. You have to use Gibbon version >= 2.1.3 to send campaigns, because there was a bug in the earlier versions.
Gibbon's readme file was recently updated with examples.
To create a campaign:
recipients = {
list_id: list_id,
segment_opts: {
saved_segment_id: segment_id
}
}
settings = {
subject_line: "Subject Line",
title: "Name of Campaign",
from_name: "From Name",
reply_to: "my#email.com"
}
body = {
type: "regular",
recipients: recipients,
settings: settings
}
begin
gibbon.campaigns.create(body: body)
rescue Gibbon::MailChimpError => e
puts "Houston, we have a problem: #{e.message} - #{e.raw_body}"
end
To send a campaign:
gibbon.campaigns(campaign_id).actions.send.create
To get stats:
email_stats = gibbon.reports(campaign_id).retrieve["opens"]

Stripe: Cannot charge a customer that has no active card

I am trying to create a customer and charge that customer using Rails and Stripe. The customer is getting created in Stripe, but I keep getting the error Cannot charge a customer that has no active card when trying to do the charge.
I am following a stripe tutorial as a Rails beginner, so I'm not sure where to go from here. Any help would be greatly appreciated.
Rails code:
def process_payment
customer = Stripe::Customer.create email: email,
card: card_token
Stripe::Charge.create customer: customer.id,
amount: level.price*100,
description: level.name,
card: card_token,
currency: 'usd'
end
def create
#registration = Registration.new registration_params.merge(email: stripe_params["stripeEmail"],
card_token: stripe_params["stripeToken"])
raise "Please, check registration errors" unless #registration.valid?
#registration.process_payment
#registration.save
redirect_to #registration, notice: 'Registration was successfully created.'
end
Try creating the charge without the card_token. You shouldn't need to specify the card a second time, since the card is attached to the customer, which you're specifying though the customer parameter.
customer = Stripe::Customer.create email: email,
source: card_token
Stripe::Charge.create customer: customer.id,
amount: level.price*100,
description: level.name,
currency: 'usd'
Also, pass the card_token through the source param, rather than the deprecated card param. Here is a blog post that talks about this change: https://stripe.com/blog/unifying-payment-types-in-the-api
More info: https://stripe.com/docs/api/ruby#create_customer
and: https://stripe.com/docs/api#create_charge
What you are trying to do is charge a customer once you have created a payment method for her. However, you cannot use the Charge endpoint to do that if you have not set any subscriptions because this method is made for recurring payments linked to subscriptions.
In order to be able to charge your client, set a subscription. This will activate the card. You'll then be able to debit the card.
You're trying to access the parameters, so you must use the params keyword.
Instead of card_token, use params["card_token"]

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

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
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.
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.
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?"

Devise Invitable - Update user associated tables only in callback

I'm trying to do a test send using
u = User.invite!({:email => "myemail#live.com", :name => "John Doe"}, User.find(1))
Why is Devise Invitable trying to insert into tables companies and company_roles with wierd/wrong values when I'm actually expecting only the user table to be updated.
This behaviour causes a ROLLBACK since the invite does not have the correct values to update these tables.
I only want to save stuff like company_role in the callback after the user has accepted an invite. How do I do this in the callback function and how do I access the initial values sent by the invite.
For example, can I do this?
u = #referrer.invite!({
email: params[:email],
title: params[:title],
first_name: params[:first_name],
last_name: params[:last_name],
website: #website,
company_id: #company,
country: #country,
}, #referrer)
And then later retrieve some of the values in the accept callback using this in the User model?
after_invitation_accepted :email_invited_by
def email_invited_by
# ...
end

Resources