chimpy 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/README.rdoc +3 -0
- data/Rakefile +8 -0
- data/chimpy.gemspec +37 -0
- data/fixtures/vcr_cassettes/run.yml +34 -0
- data/fixtures/vcr_cassettes/succesful_list_subscription.yml +34 -0
- data/lib/chimpy.rb +22 -0
- data/lib/chimpy/base.rb +9 -0
- data/lib/chimpy/configuration.rb +11 -0
- data/lib/chimpy/email_service.rb +40 -0
- data/lib/chimpy/railtie.rb +16 -0
- data/lib/chimpy/user_manager.rb +22 -0
- data/lib/chimpy/version.rb +3 -0
- data/lib/generators/migration_generator.rb +23 -0
- data/lib/generators/templates/add_column_to_sync_class.rb.erb +5 -0
- data/lib/tasks/chimpy.rake +6 -0
- data/test/base_test.rb +36 -0
- data/test/configuration_test.rb +16 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/user.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20140509170116_create_users.rb +11 -0
- data/test/dummy/db/migrate/20140513015907_remove_column_from_users.rb +5 -0
- data/test/dummy/db/migrate/20140513022907_add_chimpy_to_users.rb +5 -0
- data/test/dummy/db/schema.rb +24 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/test/fixtures/users.yml +11 -0
- data/test/dummy/test/models/user_test.rb +7 -0
- data/test/email_service_test.rb +26 -0
- data/test/test_helper.rb +44 -0
- data/test/user_manager_test.rb +35 -0
- metadata +341 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2c969ef0d51ce19648c2fef489ec6b596d1c32df
|
4
|
+
data.tar.gz: d2a8eb0e5fc334e4e8506367ed472f9fa2862312
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 339cc748a5107dedc441e986e6eed947a57e02d5989cb0730a1e3eb987eab9809c6b0b792a9cb9a8fc909794775654101c1e52de8dcbb5cc8a03ad1c2e5be057
|
7
|
+
data.tar.gz: 9240d729f13d671a2a06936eb741adebe60af4951c4fcb5735e399f74f94065f90b90273572a463b53693dc2cd4bfcec06f38a96dace8f35cd046e434440740c
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.env
|
19
|
+
.DS_Store
|
20
|
+
test/dummy/log/
|
21
|
+
test/dummy/log/development.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ignacio Gutierrez
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Chimpy
|
2
|
+
|
3
|
+
Chimpy syncs your users from your DB to your respective lists in MailChimp.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'chimpy'
|
10
|
+
|
11
|
+
Then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Create an initializer with the details for the class you would like to sync with MailChimp and your mailchimp keys. It defaults to User
|
16
|
+
|
17
|
+
``` ruby
|
18
|
+
#initializers/chimpy.rb
|
19
|
+
|
20
|
+
Chimpy.configure do |config|
|
21
|
+
config.sync_class = User
|
22
|
+
config.mailchimp_api_key = "549391d6ed3fc64fd42e4b5cf83ceba9-us8"
|
23
|
+
config.mailchimp_list_id = "788e29440b"
|
24
|
+
end
|
25
|
+
|
26
|
+
```
|
27
|
+
Run Chimpy Generator
|
28
|
+
|
29
|
+
$ rails g chimpy:migrate
|
30
|
+
|
31
|
+
After that execute the generated migration
|
32
|
+
|
33
|
+
$ rake db:migration
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
To sync your users just run the following rake task. It is recommended to run it frequently with a cron or schedule it with Heroku Scheduler.
|
38
|
+
|
39
|
+
$ rake chimpy:sync
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it ( http://github.com/<my-github-username>/chimpy/fork )
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create new Pull Request
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
data/chimpy.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'chimpy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "chimpy"
|
8
|
+
spec.version = Chimpy::VERSION
|
9
|
+
spec.authors = ["Ignacio Gutierrez"]
|
10
|
+
spec.email = ["nachojgutierrez@gmail.com"]
|
11
|
+
spec.summary = %q{Chimpy syncs your users from your DB to your respective lists in MailChimp.}
|
12
|
+
spec.description = %q{Chimpy syncs your users from your DB to your respective lists in MailChimp.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency'gibbon', '>= 1.1.2'
|
22
|
+
spec.add_dependency 'railties', '>= 3.0.0'
|
23
|
+
spec.add_dependency 'activerecord', '>= 3.0.0'
|
24
|
+
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "minitest"
|
29
|
+
spec.add_development_dependency "dotenv"
|
30
|
+
spec.add_development_dependency "webmock"
|
31
|
+
spec.add_development_dependency "database_cleaner"
|
32
|
+
spec.add_development_dependency "vcr"
|
33
|
+
|
34
|
+
spec.add_development_dependency "rails", ">= 4.0.2"
|
35
|
+
spec.add_development_dependency "sqlite3"
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://us8.api.mailchimp.com/2.0/lists/batch-subscribe
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: '{"apikey":"549391d6ed3fc64fd42e4b5cf83ceba9-us8","id":"788e29440b","batch":[{"email":{"email":"david.gilmour@gmail.com"}},{"email":{"email":"nick.mason@gmail.com"}}],"update_existing":true,"double_optin":false}'
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Server:
|
16
|
+
- nginx
|
17
|
+
Content-Type:
|
18
|
+
- application/json; charset=utf-8
|
19
|
+
Content-Length:
|
20
|
+
- '229'
|
21
|
+
Vary:
|
22
|
+
- Accept-Encoding
|
23
|
+
Date:
|
24
|
+
- Sat, 10 May 2014 23:03:46 GMT
|
25
|
+
Connection:
|
26
|
+
- keep-alive
|
27
|
+
Set-Cookie:
|
28
|
+
- _AVESTA_ENVIRONMENT=prod; path=/
|
29
|
+
body:
|
30
|
+
encoding: UTF-8
|
31
|
+
string: '{"add_count":2,"adds":[{"email":"david.gilmour@gmail.com","euid":"0a80c3e59f","leid":"151471181"},{"email":"nick.mason@gmail.com","euid":"678343bc63","leid":"151471185"}],"update_count":0,"updates":[],"error_count":0,"errors":[]}'
|
32
|
+
http_version:
|
33
|
+
recorded_at: Sat, 10 May 2014 23:03:44 GMT
|
34
|
+
recorded_with: VCR 2.8.0
|
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://us8.api.mailchimp.com/2.0/lists/batch-subscribe
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: '{"apikey":"549391d6ed3fc64fd42e4b5cf83ceba9-us8","id":"788e29440b","batch":[{"email":{"email":"johndonson@gmail.com"}},{"email":{"email":"donjohnson@gmail.com"}}],"update_existing":true,"double_optin":false}'
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Server:
|
16
|
+
- nginx
|
17
|
+
Content-Type:
|
18
|
+
- application/json; charset=utf-8
|
19
|
+
Content-Length:
|
20
|
+
- '227'
|
21
|
+
Vary:
|
22
|
+
- Accept-Encoding
|
23
|
+
Date:
|
24
|
+
- Fri, 09 May 2014 21:17:33 GMT
|
25
|
+
Connection:
|
26
|
+
- keep-alive
|
27
|
+
Set-Cookie:
|
28
|
+
- _AVESTA_ENVIRONMENT=prod; path=/
|
29
|
+
body:
|
30
|
+
encoding: UTF-8
|
31
|
+
string: '{"add_count":2,"adds":[{"email":"johndonson@gmail.com","euid":"d4c1408824","leid":"151330921"},{"email":"donjohnson@gmail.com","euid":"7f18d87748","leid":"151330925"}],"update_count":0,"updates":[],"error_count":0,"errors":[]}'
|
32
|
+
http_version:
|
33
|
+
recorded_at: Fri, 09 May 2014 21:17:33 GMT
|
34
|
+
recorded_with: VCR 2.8.0
|
data/lib/chimpy.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'chimpy/version'
|
2
|
+
require 'chimpy/configuration'
|
3
|
+
require 'chimpy/base'
|
4
|
+
require 'chimpy/user_manager'
|
5
|
+
require 'chimpy/email_service'
|
6
|
+
require 'chimpy/railtie' if defined?(Rails)
|
7
|
+
|
8
|
+
|
9
|
+
module Chimpy
|
10
|
+
|
11
|
+
def self.run
|
12
|
+
Base.run
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configuration
|
16
|
+
@configuration ||= Configuration.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configure
|
20
|
+
yield(configuration)
|
21
|
+
end
|
22
|
+
end
|
data/lib/chimpy/base.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module Chimpy
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :sync_class, :mailchimp_api_key, :mailchimp_list_id
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@sync_class = User
|
7
|
+
@mailchimp_api_key = ENV['MAILCHIMP_API_KEY']
|
8
|
+
@mailchimp_list_id = ENV['MAILCHIMP_LIST_ID']
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'gibbon'
|
2
|
+
|
3
|
+
module Chimpy
|
4
|
+
class EmailService
|
5
|
+
attr_reader :mailchimp, :mailchimp_api_key, :mailchimp_list_id
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@mailchimp_api_key = Chimpy.configuration.mailchimp_api_key
|
9
|
+
@mailchimp_list_id = Chimpy.configuration.mailchimp_list_id
|
10
|
+
@mailchimp = create_mailchimp_client
|
11
|
+
end
|
12
|
+
|
13
|
+
def sync(users)
|
14
|
+
struct = users.map { |user| { email: { email: user.email } } }
|
15
|
+
response = mailchimp.lists.batch_subscribe(id: mailchimp_list_id,
|
16
|
+
batch: struct,
|
17
|
+
update_existing: true,
|
18
|
+
double_optin: false)
|
19
|
+
synced_users(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def synced_users(response)
|
25
|
+
emails = []
|
26
|
+
response['adds'].each do |add|
|
27
|
+
emails << add['email']
|
28
|
+
end
|
29
|
+
|
30
|
+
response['updates'].each do |update|
|
31
|
+
emails << update['email']
|
32
|
+
end
|
33
|
+
emails
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_mailchimp_client
|
37
|
+
Gibbon::API.new(mailchimp_api_key)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Chimpy
|
2
|
+
class UserManager
|
3
|
+
attr_reader :sync_class
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@sync_class = Chimpy.configuration.sync_class
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_sync
|
10
|
+
never_synced = sync_class.where(chimpy_synced_at: nil)
|
11
|
+
needing_sync = sync_class.where('updated_at > chimpy_synced_at')
|
12
|
+
never_synced + needing_sync
|
13
|
+
end
|
14
|
+
|
15
|
+
def mark_as_synced(emails)
|
16
|
+
emails.each do |email|
|
17
|
+
found = sync_class.find_by_email(email)
|
18
|
+
found.update(chimpy_synced_at: Time.now) if found
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
|
5
|
+
module Chimpy
|
6
|
+
class MigrationGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
|
10
|
+
def copy_files
|
11
|
+
@sync_class = Chimpy.configuration.sync_class.to_s
|
12
|
+
migration_template('add_column_to_sync_class.rb.erb', "db/migrate/add_chimpy_to_#{@sync_class.underscore.pluralize}.rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.next_migration_number(dirname) #:nodoc:
|
16
|
+
if ActiveRecord::Base.timestamped_migrations
|
17
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
18
|
+
else
|
19
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Chimpy::Base do
|
4
|
+
|
5
|
+
before do
|
6
|
+
Chimpy.configure do |config|
|
7
|
+
config.sync_class = User
|
8
|
+
config.mailchimp_api_key = "549391d6ed3fc64fd42e4b5cf83ceba9-us8"
|
9
|
+
config.mailchimp_list_id = "788e29440b"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "run" do
|
14
|
+
before do
|
15
|
+
@new_user = User.create(email: "david.gilmour@gmail.com")
|
16
|
+
@already_synced = User.create(email: "roger.waters@gmail.com", chimpy_synced_at: 1.day.ago, updated_at: 3.days.ago)
|
17
|
+
@to_sync = User.create(email: "nick.mason@gmail.com", chimpy_synced_at: 5.days.ago, updated_at: 1.day.ago)
|
18
|
+
VCR.use_cassette('run') do
|
19
|
+
Chimpy.run
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "syncs the new user" do
|
24
|
+
@new_user.reload.chimpy_synced_at.wont_equal nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "syncs the user who needs sync" do
|
28
|
+
@to_sync.chimpy_synced_at.must_be :<, @to_sync.reload.chimpy_synced_at
|
29
|
+
end
|
30
|
+
|
31
|
+
it "leaves the already synced user untouched" do
|
32
|
+
@already_synced.chimpy_synced_at.must_equal @already_synced.reload.chimpy_synced_at
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Chimpy::Configuration do
|
4
|
+
describe "#sync_class" do
|
5
|
+
it "default value is User" do
|
6
|
+
Chimpy::Configuration.new.sync_class.must_equal User
|
7
|
+
end
|
8
|
+
end
|
9
|
+
describe "#sync_class=" do
|
10
|
+
it "can set value" do
|
11
|
+
config = Chimpy::Configuration.new
|
12
|
+
config.sync_class = Object.const_set("Admin" ,Class.new)
|
13
|
+
config.sync_class.must_equal Admin
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|