emma-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +21 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +51 -0
- data/LICENSE +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +96 -0
- data/Rakefile +8 -0
- data/emma.gemspec +26 -0
- data/lib/emma.rb +40 -0
- data/lib/emma/api/fields.rb +37 -0
- data/lib/emma/api/groups.rb +62 -0
- data/lib/emma/api/mailings.rb +77 -0
- data/lib/emma/api/members.rb +135 -0
- data/lib/emma/api/response.rb +36 -0
- data/lib/emma/api/searches.rb +38 -0
- data/lib/emma/api/triggers.rb +37 -0
- data/lib/emma/api/webhooks.rb +42 -0
- data/lib/emma/client.rb +92 -0
- data/lib/emma/configurable.rb +21 -0
- data/lib/emma/version.rb +3 -0
- data/test/helper.rb +14 -0
- data/test/test_emma_interface.rb +88 -0
- data/test/test_emma_methods.rb +598 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4c343b5b6b7dbe54e1382f838b37c6c5b50bce1e
|
4
|
+
data.tar.gz: 50775b93e195e3c24b27722c2f57a69c5f7b7584
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bfc4fe896e5c5db5fce0b58198a9a8dbc9a0710ab51e51197e03671eacafde5a6c934ffed6d723d72394d8508a97f401d500b2bbac76cf9996a448b024d5dd57
|
7
|
+
data.tar.gz: 367fc8e691315a89bd0f9fb4369997de2e0afff9f05fcf401e3aa5014b2d4a67f182ba837869f963da011484bed7fc36bd2609ac829a6b584904db3fbeb52ba3
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
language: ruby
|
3
|
+
rvm:
|
4
|
+
- 1.9.2
|
5
|
+
- 1.9.3
|
6
|
+
script:
|
7
|
+
- bundle exec rake run_tests
|
8
|
+
env:
|
9
|
+
global:
|
10
|
+
- secure: |-
|
11
|
+
UgkY7PDsbBfq3Ukyzb6VIWXY6zd7s8bJMLOkkQ7RK7huwl68jfeYSpLwJ6Rm
|
12
|
+
2qVaYj84YDmSwr6ed6Fk2C+1IviqlN4NkJ0c9JtibHHOVOxBB8Y+dm17DFPp
|
13
|
+
jsIOOUB/NduVNOlIKMCwCiXFEPBTwhiWLFGEkE4HHLk3HnxHaj8=
|
14
|
+
- secure: |-
|
15
|
+
agxJsFr30M/dvbj2+tqBHmklouxk8+PRO+DBJOEWdGBxjJVis0kcDsFCp3sa
|
16
|
+
V0TqnS/+7ExVOjez4b6r9NSNrBmxhQuVYEr1Wsk96CE1B16Y1XsCImvIooxl
|
17
|
+
KPJWYy2szbex7i8ibCkA7w0Yvb8QhmHMLAa3aVtteEOAGULyCr4=
|
18
|
+
- secure: |-
|
19
|
+
jqHIRzqNXdFT/QIksVfMYFSHAiFKOY16hNjyWQr8g7g/DuFAIdjO7zhCqK7H
|
20
|
+
bDQ0RDqw84MNnrCFdctvxE6n4nHO3guM4BYLSAENflXVAugzlve5BTFRZfbz
|
21
|
+
qJ5cboa3VSwZeks/PYoIIwbaFCpVlMulEMRgKl0YjDs/y9RhcYo=
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
emma-ruby (0.0.1)
|
5
|
+
httparty
|
6
|
+
json
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activesupport (3.2.11)
|
12
|
+
i18n (~> 0.6)
|
13
|
+
multi_json (~> 1.0)
|
14
|
+
addressable (2.5.2)
|
15
|
+
public_suffix (>= 2.0.2, < 4.0)
|
16
|
+
crack (0.4.3)
|
17
|
+
safe_yaml (~> 1.0.0)
|
18
|
+
hashdiff (0.3.6)
|
19
|
+
httparty (0.15.6)
|
20
|
+
multi_xml (>= 0.5.2)
|
21
|
+
i18n (0.8.6)
|
22
|
+
json (2.1.0)
|
23
|
+
multi_json (1.5.0)
|
24
|
+
multi_xml (0.6.0)
|
25
|
+
public_suffix (3.0.0)
|
26
|
+
rake (12.1.0)
|
27
|
+
safe_yaml (1.0.4)
|
28
|
+
shoulda (3.3.2)
|
29
|
+
shoulda-context (~> 1.0.1)
|
30
|
+
shoulda-matchers (~> 1.4.1)
|
31
|
+
shoulda-context (1.0.2)
|
32
|
+
shoulda-matchers (1.4.1)
|
33
|
+
activesupport (>= 3.0.0)
|
34
|
+
vcr (3.0.3)
|
35
|
+
webmock (3.0.1)
|
36
|
+
addressable (>= 2.3.6)
|
37
|
+
crack (>= 0.3.2)
|
38
|
+
hashdiff
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
ruby
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
emma-ruby!
|
45
|
+
rake
|
46
|
+
shoulda
|
47
|
+
vcr
|
48
|
+
webmock
|
49
|
+
|
50
|
+
BUNDLED WITH
|
51
|
+
1.13.7
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2013 Emma, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Dennis Monsewicz
|
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,96 @@
|
|
1
|
+
## Emma API Wrapper (Ruby)
|
2
|
+
A Ruby wrapper for Emma's API.
|
3
|
+
|
4
|
+
## Running the tests [![Build Status](https://travis-ci.org/myemma/EmmaRuby.png)](https://travis-ci.org/myemma/EmmaRuby)
|
5
|
+
Set the following environment values
|
6
|
+
|
7
|
+
```bash
|
8
|
+
export EMMA_ACCOUNT_ID=123456
|
9
|
+
export EMMA_PUBLIC_KEY=6fbfd5e68d3306e51350
|
10
|
+
export EMMA_PRIVATE_KEY=53f42aa48e24d44a3362
|
11
|
+
```
|
12
|
+
|
13
|
+
Run the tests
|
14
|
+
|
15
|
+
```
|
16
|
+
bundle exec rake run_tests
|
17
|
+
```
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add this line to your application's Gemfile:
|
22
|
+
|
23
|
+
gem 'emma'
|
24
|
+
|
25
|
+
And then execute:
|
26
|
+
|
27
|
+
$ bundle
|
28
|
+
|
29
|
+
Or install it yourself as:
|
30
|
+
|
31
|
+
$ gem install emma
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
## Instantiation
|
36
|
+
```ruby
|
37
|
+
require 'emma'
|
38
|
+
em = Emma::Setup.new 'account_id', 'public_key', 'private_key', 'debug_true_or_false'
|
39
|
+
```
|
40
|
+
|
41
|
+
You can also set environment variables and the Emma Wrapper will use them when you create an instance
|
42
|
+
```ruby
|
43
|
+
ENV['EMMA_ACCOUNT_ID'] = 'account_id'
|
44
|
+
ENV['EMMA_PUBLIC_KEY'] = 'public_key'
|
45
|
+
ENV['EMMA_PRIVATE_KEY'] = 'private_key'
|
46
|
+
em = Emma::Setup.new
|
47
|
+
```
|
48
|
+
|
49
|
+
## GET Request
|
50
|
+
```ruby
|
51
|
+
req = em.my_members
|
52
|
+
# Will return a members array
|
53
|
+
puts req.inspect
|
54
|
+
```
|
55
|
+
|
56
|
+
## Pagination
|
57
|
+
```ruby
|
58
|
+
req = em.my_members count: true
|
59
|
+
# Will return a count of all of the members tied to your account
|
60
|
+
puts req.inspect
|
61
|
+
```
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
req = em.my_members start: 0, end: 200
|
65
|
+
# Will return a members array starting with the specified start param and ending with the specified end param
|
66
|
+
puts req.inspect
|
67
|
+
```
|
68
|
+
|
69
|
+
## POST Request
|
70
|
+
```ruby
|
71
|
+
req = em.add_member email: "helloworld@gmail.com", fields: { first_name: 'hello', last_name: 'world' }
|
72
|
+
# Will return a reference object of the newly added member
|
73
|
+
puts req.inspect
|
74
|
+
```
|
75
|
+
|
76
|
+
## PUT Request
|
77
|
+
```ruby
|
78
|
+
req = em.update_member 111, status: 'e'
|
79
|
+
# Will return true if the member was updated
|
80
|
+
puts req.inspect
|
81
|
+
```
|
82
|
+
|
83
|
+
## DELETE Request
|
84
|
+
```ruby
|
85
|
+
req = em.remove_member 111
|
86
|
+
# Will return true if the member was deleted
|
87
|
+
puts req.inspect
|
88
|
+
```
|
89
|
+
|
90
|
+
## Contributing
|
91
|
+
|
92
|
+
1. Fork it
|
93
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
94
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
95
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
96
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/emma.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'emma/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "emma-ruby"
|
7
|
+
s.version = Emma::VERSION
|
8
|
+
s.authors = ["Dennis Monsewicz"]
|
9
|
+
s.email = ["dennismonsewicz@gmail.com"]
|
10
|
+
s.description = %q{A simple wrapper for integration with Emma's API'}
|
11
|
+
s.summary = %q{A simple wrapper for integration with Emma's API}
|
12
|
+
s.homepage = ""
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
16
|
+
s.test_files = `git ls-files -- {test}/*`.split '\n'
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency 'httparty'
|
20
|
+
s.add_dependency 'json'
|
21
|
+
|
22
|
+
s.add_development_dependency 'rake'
|
23
|
+
s.add_development_dependency 'shoulda'
|
24
|
+
s.add_development_dependency 'vcr'
|
25
|
+
s.add_development_dependency 'webmock'
|
26
|
+
end
|
data/lib/emma.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "emma/version"
|
2
|
+
require "emma/client"
|
3
|
+
require "emma/configurable"
|
4
|
+
|
5
|
+
module Emma
|
6
|
+
class << self
|
7
|
+
def available_categories
|
8
|
+
[:fields, :groups, :mailings, :members, :response, :searches, :triggers, :webhooks]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Setup
|
13
|
+
include Emma::Configurable
|
14
|
+
|
15
|
+
attr_accessor :account_id, :public_key, :private_key, :debug
|
16
|
+
|
17
|
+
def initialize(account_id = nil, public_key = nil, private_key = nil, debug = false)
|
18
|
+
@account_id = account_id || ENV['EMMA_ACCOUNT_ID']
|
19
|
+
@public_key = public_key || ENV['EMMA_PUBLIC_KEY']
|
20
|
+
@private_key = private_key || ENV['EMMA_PRIVATE_KEY']
|
21
|
+
@debug = debug
|
22
|
+
end
|
23
|
+
|
24
|
+
# establish connection
|
25
|
+
def client
|
26
|
+
@client = Emma::Client.new(options) unless defined?(@client) && @client.hash == options.hash
|
27
|
+
@client
|
28
|
+
end
|
29
|
+
|
30
|
+
def respond_to_missing?(method, include_private = false)
|
31
|
+
client.respond_to?(client, include_private)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def method_missing(method_name, *args)
|
36
|
+
return super unless client.respond_to?(method_name)
|
37
|
+
client.send(method_name, *args)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# @see http://api.myemma.com/api/external/fields.html
|
2
|
+
|
3
|
+
module Emma
|
4
|
+
module API
|
5
|
+
module Fields
|
6
|
+
# Gets a list of this account’s defined fields.
|
7
|
+
def my_fields(params = {})
|
8
|
+
get("/fields", params)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Gets the detailed information about a particular field.
|
12
|
+
def get_field_by_id(id, params = {})
|
13
|
+
get("/fields/#{id}", params)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Create a new field
|
17
|
+
def add_field(params = {})
|
18
|
+
post("/fields", params)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Delete a field
|
22
|
+
def remove_field(id)
|
23
|
+
delete("/fields/#{id}")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Clear the member data for the specified field.
|
27
|
+
def remove_member_data_for_field(id)
|
28
|
+
post("/fields/#{id}/clear")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Updates an existing field.
|
32
|
+
def update_field(id, params = {})
|
33
|
+
put("/fields/#{id}", params)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# @see http://api.myemma.com/api/external/groups.html
|
2
|
+
|
3
|
+
module Emma
|
4
|
+
module API
|
5
|
+
module Groups
|
6
|
+
# Get a basic listing of all active member groups for a single account.
|
7
|
+
def my_groups(params = {})
|
8
|
+
get("/groups", params)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Create one or more new member groups.
|
12
|
+
def add_new_groups(params = {})
|
13
|
+
post("/groups", params)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get the detailed information for a single member group.
|
17
|
+
def get_group_by_id(id)
|
18
|
+
get("/groups/#{id}")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Update information for a single member group.
|
22
|
+
def update_group(id, params = {})
|
23
|
+
put("/groups/#{id}", params)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Delete a single member group.
|
27
|
+
def remove_group(id)
|
28
|
+
delete("/groups/#{id}")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get the members in a single active member group.
|
32
|
+
def group_members(id, params = {})
|
33
|
+
get("/groups/#{id}/members", params)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add a list of members to a single active member group.
|
37
|
+
def add_members_to_group(id, params = {})
|
38
|
+
put("/groups/#{id}/members", params)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Remove members from a single active member group.
|
42
|
+
def remove_members_from_group(id, params = {})
|
43
|
+
put("/groups/#{id}/members/remove", params)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Remove all members from a single active member group.
|
47
|
+
def remove_all_members_from_group(id, params = {})
|
48
|
+
delete("/groups/#{id}/members", params)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Remove all members from all active member groups as a background job. The member_status_id parameter must be set.
|
52
|
+
def remove_all_members_from_groups(id, params = {})
|
53
|
+
delete("/groups/#{id}/members/remove", params)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Copy all the users of one group into another group.
|
57
|
+
def copy_members_to_different_group(from_id, to_id, params = {})
|
58
|
+
put("/groups/#{from_id}/#{to_id}/members/copy", params)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# @see http://api.myemma.com/api/external/mailings.html
|
2
|
+
|
3
|
+
module Emma
|
4
|
+
module API
|
5
|
+
module Mailings
|
6
|
+
# Get information about current mailings.
|
7
|
+
def my_mailings(params = {})
|
8
|
+
get("/mailings", params)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Get detailed information for one mailing.
|
12
|
+
def get_mailing_by_id(id)
|
13
|
+
get("/mailings/#{id}")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get the list of members to whom the given mailing was sent.
|
17
|
+
def get_mailing_members(id)
|
18
|
+
get("/mailings/#{id}/members")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Gets the personalized message content as sent to a specific member as part of the specified mailing.
|
22
|
+
def get_personalized_member_mailing(id, member_id, params = {})
|
23
|
+
get("/mailings/#{id}/messages/#{member_id}", params)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the groups to which a particular mailing was sent.
|
27
|
+
def get_groups_by_mailing(id, params = {})
|
28
|
+
get("/mailings/#{id}/groups", params)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get all searches associated with a sent mailing.
|
32
|
+
def mailing_searches(id, params = {})
|
33
|
+
get("/mailings/#{id}/searches", params)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Update status of a current mailing
|
37
|
+
def update_mailing(id, params = {})
|
38
|
+
put("/mailings/#{id}", params)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sets archived timestamp for a mailing so it is no longer included in mailing_list.
|
42
|
+
def remove_mailing(id)
|
43
|
+
delete("/mailings/#{id}")
|
44
|
+
end
|
45
|
+
|
46
|
+
# Cancels a mailing that has a current status of pending or paused. All other statuses will result in a 404.
|
47
|
+
def cancel_queued_mailing(id)
|
48
|
+
delete("/mailings/cancel/#{id}")
|
49
|
+
end
|
50
|
+
|
51
|
+
# Forward a previous message to additional recipients. If these recipients are not already in the audience, they will be added with a status of FORWARDED.
|
52
|
+
def forward_mailing_to_additional_recipients(id, member_id, params = {})
|
53
|
+
post("/forwards/#{id}/#{member_id}", params)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Send a prior mailing to additional recipients. A new mailing will be created that inherits its content from the original.
|
57
|
+
def send_existing_mailing(id, params = {})
|
58
|
+
post("/mailings/#{id}", params)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Get heads up email address(es) related to a mailing.
|
62
|
+
def mailing_headsup(id)
|
63
|
+
get("/mailings/#{id}/headsup")
|
64
|
+
end
|
65
|
+
|
66
|
+
# Validate that a mailing has valid personalization-tag syntax
|
67
|
+
def validate_mailing(params = {})
|
68
|
+
post("/mailings/validate", params)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Declare the winner of a split test manually. In the event that the test duration has not elapsed, the current stats for each test will be frozen and the content defined in the user declared winner will sent to the remaining members for the mailing. Please note, any messages that are pending for each of the test variations will receive the content assigned to them when the test was initially constructed.
|
72
|
+
def declare_winner_of_split_test(mailing_id, winner_id)
|
73
|
+
post("/mailings/#{mailing_id}/winner/#{winner_id}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|