ruby-on-railsherokumailchimpgibbonlearn-ruby-on-rails

Heroku needs different code to set environmental variable but why?


For the first time I have a question to an answer I already solved, this is more about WHY my little fix solved it in the first place.

I'm following the Learn Rails book tutorial by Daniel Kehoe, creating an application that is supposed to subscribe people to a MailChimp list. I'm using the Gibbon gem, and in the book this is (part of) the code in the model used to set the variables:

def subscribe
  mailchimp = Gibbon::API.new(Rails.application.secrets.mailchimp_api_key)
  result = mailchimp.lists.subscribe({
    :id => Rails.application.secrets.mailchimp_list_id,
  <more code here for email and stuff>
end

My secrets.yml file for the variables in question looks like this:

mailchimp_api_key: <%= ENV["MAILCHIMP_API_KEY"] %>
mailchimp_list_id: <%= ENV["MAILCHIMP_LIST_ID"] %>

And, since I'm on Windows, I set the actual value of them in application.yml: [Edit: As people have pointed out, this comes from the Figaro gem and may or may not be part of the tutorial]

MAILCHIMP_API_KEY: mysecretkey
MAILCHIMP_LIST_ID: mysecretid

This, I should note, works perfectly fine locally. I can run my server and subscribe. However, pushing it to Heroku and setting the ENV variables via heroku config:set MAILCHIMP_API_KEY=mysecretkey and the same thing for MAILCHIMP_LIST_ID, it doesn't work. More specifically, it returns the error Invalid Mailchimp List ID:.

So, despite setting it and checking that it is actually set, it has no value at all for the List ID.

I fixed the problem by searching through Heroku's own help text on Config Vars, where it recommends the following: "Set up your code to read the vars at runtime. For example, in Ruby you access the environment variables using the ENV['KEY'] pattern"

I changed my code in the model, so instead of using Rails.application.secrets.mailchimp_list_id it's now this:

def subscribe
  mailchimp = Gibbon::API.new(Rails.application.secrets.mailchimp_api_key)
  result = mailchimp.lists.subscribe({
    :id => ENV['MAILCHIMP_LIST_ID'],
  <more code here for email and stuff>
end

And, what do you know, it works in Heroku (and locally)! Why, though? I mean, it did understand the same kind of code for the API Key, but not for the list ID, which seems strange to me. Also, how come the book in question doesn't reflect on this? The author seems willing to update it very regularly, and I see him answer questions on it with an almost religious dedication. Am I the only one to run into this problem?

Edit: Solved below. I feel a bit silly now, and as usual things have a very easy solution. I will note that the book did in fact have the keys duplicated into production in the secrets.yml file, I just missed that part, probably because I had to find an alternative solution to the whole problem of environmental variables and using the Figaro gem. If I have any criticism of the book, it's that it doesn't cater to us poor Windows users. :)


Solution

  • Figaro creates the config/application.yml file and according to its documentation, adds it to your .gitignore:

    This creates a commented config/application.yml file and adds it to your .gitignore. Add your own configuration to this file and you're done!

    This is done to prevent sensitive secrets (like passwords and salts) from being committed into your Git repository, where those secrets would be compromised.

    Figaro does have a feature which you can use to transfer all the settings in application.yml to Heroku at once by running

    figaro heroku:set -e production
    

    As it turns out, the config/secrets.yml did not repeat the Mailchimp keys in the production section. To fix this, it should look like this:

    development:
      mailchimp_api_key: <%= ENV["MAILCHIMP_API_KEY"] %>
      mailchimp_list_id: <%= ENV["MAILCHIMP_LIST_ID"] %>
    
    production:
      mailchimp_api_key: <%= ENV["MAILCHIMP_API_KEY"] %>
      mailchimp_list_id: <%= ENV["MAILCHIMP_LIST_ID"] %>