Writing a DataMapper Adapter to Access MailChimp Web Services From Merb

As I mentioned in my last post, I’ve started looking into writing DataMapper Adapters, using my MailChimp wrapper as an example. Thus far, I’ve been pretty impressed with the Adapter layer built into DataMapper and the possibilities this abstraction layer provides. A quick search over at GitHub will show you all the interesting things folks are doing with adapters.

Anyway, here’s a synopsis of what I’ve come across thus far. As pointed out in this post by The Merbist, a custom adapter simply inherits from Abstract Adapter and as such, can define a number of default Adapter methods such as create, update, delete, read_one and read_many. You also have access to an initialization method that supplies a hash with important environment information, including any parameters relevant to your adapter that a user may have setup in a database.yml file. This allowed me to create a MailChimp client and login once during class initialization rather than at every request, so I got that going for me.

Once I had a MailChimp client setup with login information, I started getting create working in my adapter. The create method takes a collection of resources as an option which I simply loop through and call the MailChimp listSubscribe API. So far, so good. I now wanted to test whether any of this would work with Merb.

I created a merb app:


 merb-gen app campaign
 cd campaign

and set the :use_orm parameter to datamapper in the Merb init.rb.

Next, I ran rake dm:db:database_yaml in order to generate a database.yml file to specify relevant properties for my adapter. In my case, I needed to create an entry for my mailchimp adapter:


  adapter:  mailchimp
  database:
  username: user
  password: password
  mailing_list_id: list_id
  host: localhost

.

I next created a resource to test the adapter with by running merb-gen resource mailings. My thinking was that one could have a User stored in a relational (or other) datastore, and that User can have many mailings or some such thing, bad naming aside. Anyway, a cool feature of DataMapper is that you can specify any number of repositories in a database.yml with different adapters, and then specify on a resource by resource basis which repository a resource belongs to like so:


 def self.default_repository_name
      :mysql
 end

After generating my resource, I went in to add the properties MailChimp would require for the create method.


class Mailings
  include DataMapper::Resource

  property :id, String, :serial => true, :key => true, :field => :_id
  property :first_name, String
  property :last_name, String
  property :email, String
  property :mailing_list_id, String

   def build_mail_merge()
      {"EMAIL" => self.email, "FNAME" => self.first_name, "LNAME" => self.last_name }
   end
end

.

I also added a callback method that is used by the adapter in order to pass mail merge arguments to MailChimp. This seemed like a sane approach given that the MailChimp mail_merge arguments are quite dynamic.

With a resource firmly in place, I fired up the merb console and tested to see whether I could connect to MailChimp with it.


 m = Mailing.new
 m.first_name = 'mandarin'
 m.last_name = 'soda'
 m.email = 'msoda@disney.com'
 m.mailing_list_id = '9'
 m.create

I checked my disney email, and sure enough, I had an opt-in response from MailChimp. Victory Adapter! I could sign users up to MailChimp via the DataMapper APIs quite quickly….not too shabby.

That’s where I’m at for now…still have some things to iron out, one being that DataMapper is returning false after a successful create. Others, of course being that I need to figure out the rest of the default Adapter methods. Feel free to follow on GitHub if you feel so inclined.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Leave a Reply