customerio 2.2.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -15
- data/.circleci/config.yml +61 -0
- data/CHANGELOG.markdown +14 -0
- data/README.md +39 -14
- data/customerio.gemspec +2 -2
- data/lib/customerio.rb +3 -0
- data/lib/customerio/api.rb +34 -0
- data/lib/customerio/base_client.rb +87 -0
- data/lib/customerio/client.rb +45 -143
- data/lib/customerio/requests/send_email_request.rb +49 -0
- data/lib/customerio/version.rb +1 -1
- data/spec/api_client_spec.rb +130 -0
- data/spec/base_client_spec.rb +67 -0
- data/spec/client_spec.rb +244 -224
- metadata +39 -33
- data/.travis.yml +0 -9
checksums.yaml
CHANGED
@@ -1,17 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
YTcyNTM4NDY5MjM4OTBiOTNlOA==
|
6
|
-
data.tar.gz: !binary |-
|
7
|
-
NDE5YWFjYmM4NjQxYWU2YThhZDNhYzM0ZDdmOTU2OWExNWZmODM4YjEwY2Ri
|
8
|
-
ZTZlOWIzNzU5ZDUyZmY4ZDg5Yg==
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bd807525a01387116c22f29d0ac98e9b783fe669fd092da9d97cac74a660316d
|
4
|
+
data.tar.gz: 0ff5f3b518f07d5e3432a69e4a5738fd5bdeabc359593960bf9ac8f46081a7fc
|
9
5
|
SHA512:
|
10
|
-
metadata.gz:
|
11
|
-
|
12
|
-
Zjg5NzE2ZDg1YWI0YTg2MDY5NTkzM2QwOWNlNTAwN2U3MThmODMwODU5YTVi
|
13
|
-
YzA1ZmM2OTFmYzVkNWIxMjhhMGViNjhhODQ1ZWJkODIxODlhODg=
|
14
|
-
data.tar.gz: !binary |-
|
15
|
-
YjNiNTRlZTNkMjg2NGEwNjNiZmEyMTQyZWZhNTMyYjgxZDI1MDkxOGM4MDI1
|
16
|
-
NjRlY2U4OTBmMTM0ZTM1ZDU5M2FkNjJjNjE2ZjhmZTRiMzE0ZmE1MWJkMTQx
|
17
|
-
NDE1MDNhMWYzYmFmZTBlMTJlZDU5OGQzOGQwYjM5ZWNkMGZhOTU=
|
6
|
+
metadata.gz: 07a1b0e3472abe674a69413e81e6cf2b87c5002a3b074a26053efc0b8da2e7d91d380055c54409922d35ff2d876aeb22c956ce1ea246842ec1ce08ad3079f35b
|
7
|
+
data.tar.gz: eb291aab81e6e802a204d7c0b2d36890fa2ce26cf82c3af773a8cfddcacdc9b0d4fca7c684aee03a884bafdda4ac088c234294d197fe28041bae2573b186a1da
|
@@ -0,0 +1,61 @@
|
|
1
|
+
---
|
2
|
+
version: 2
|
3
|
+
|
4
|
+
references:
|
5
|
+
restore_cache: &restore_cache
|
6
|
+
type: cache-restore
|
7
|
+
name: Restore bundle cache
|
8
|
+
key: customerio-ruby-{{ checksum "customerio.gemspec" }}
|
9
|
+
|
10
|
+
save_cache: &save_cache
|
11
|
+
type: cache-save
|
12
|
+
name: Store bundle cache
|
13
|
+
key: customerio-ruby-{{ checksum "customerio.gemspec" }}
|
14
|
+
paths:
|
15
|
+
- vendor/bundle
|
16
|
+
|
17
|
+
jobs:
|
18
|
+
ruby_27:
|
19
|
+
working_directory: ~/customerio-ruby
|
20
|
+
docker:
|
21
|
+
- image: circleci/ruby:2.7.2
|
22
|
+
environment:
|
23
|
+
RAILS_ENV: test
|
24
|
+
steps:
|
25
|
+
- checkout
|
26
|
+
- *restore_cache
|
27
|
+
- run: bundle install
|
28
|
+
- *save_cache
|
29
|
+
- run: bundle exec rspec
|
30
|
+
ruby_26:
|
31
|
+
working_directory: ~/customerio-ruby
|
32
|
+
docker:
|
33
|
+
- image: circleci/ruby:2.6.6
|
34
|
+
environment:
|
35
|
+
RAILS_ENV: test
|
36
|
+
steps:
|
37
|
+
- checkout
|
38
|
+
- *restore_cache
|
39
|
+
- run: bundle install
|
40
|
+
- *save_cache
|
41
|
+
- run: bundle exec rspec
|
42
|
+
ruby_25:
|
43
|
+
working_directory: ~/customerio-ruby
|
44
|
+
docker:
|
45
|
+
- image: circleci/ruby:2.5.8
|
46
|
+
environment:
|
47
|
+
RAILS_ENV: test
|
48
|
+
steps:
|
49
|
+
- checkout
|
50
|
+
- *restore_cache
|
51
|
+
- run: bundle install
|
52
|
+
- *save_cache
|
53
|
+
- run: bundle exec rspec
|
54
|
+
|
55
|
+
workflows:
|
56
|
+
version: 2
|
57
|
+
test:
|
58
|
+
jobs:
|
59
|
+
- ruby_27
|
60
|
+
- ruby_26
|
61
|
+
- ruby_25
|
data/CHANGELOG.markdown
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## Customerio 3.0.0 - Dec 2, 2020
|
2
|
+
|
3
|
+
### Added
|
4
|
+
- Support for the Transactional API
|
5
|
+
|
6
|
+
### Removed
|
7
|
+
- `add_to_segment` and `remove_from_segment` methods
|
8
|
+
- Support for non-JSON data
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
- IDs in the URLs are now escaped.
|
12
|
+
- Improved validations for data that's passed in.
|
13
|
+
- Earlier, if you passed in an event name without a customer ID to the `track` method, we would create an anonymous event. That is now removed. To create an anonymous event, use the `anonymous_track` method.
|
14
|
+
|
1
15
|
## Customerio 2.2.1 - Mar 23, 2020
|
2
16
|
|
3
17
|
- Add license to gemspec [#55](https://github.com/customerio/customerio-ruby/pull/55)
|
data/README.md
CHANGED
@@ -51,12 +51,6 @@ If you're using Rails, create an initializer `config/initializers/customerio.rb`
|
|
51
51
|
$customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY")
|
52
52
|
```
|
53
53
|
|
54
|
-
If you'd like to send complex data to associate to a user as json, pass a json option:
|
55
|
-
|
56
|
-
```ruby
|
57
|
-
customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY", :json => true)
|
58
|
-
```
|
59
|
-
|
60
54
|
### Identify logged in customers
|
61
55
|
|
62
56
|
Tracking data of logged in customers is a key part of [Customer.io](http://customer.io). In order to
|
@@ -183,20 +177,51 @@ Start tracking events and identifies again for a previously suppressed customer.
|
|
183
177
|
$customerio.unsuppress(5)
|
184
178
|
```
|
185
179
|
|
186
|
-
###
|
180
|
+
### Send Transactional Messages
|
187
181
|
|
188
|
-
|
182
|
+
To use the Customer.io [Transactional API](https://customer.io/docs/transactional-api), create an instance of the API client using an [app key](https://customer.io/docs/managing-credentials#app-api-keys).
|
189
183
|
|
190
|
-
|
191
|
-
|
192
|
-
|
184
|
+
Create a new `SendEmailRequest` object containing:
|
185
|
+
|
186
|
+
* `transactional_message_id`: the ID of the transactional message you want to send, or the `body`, `from`, and `subject` of a new message.
|
187
|
+
* `to`: the email address of your recipients
|
188
|
+
* an `identifiers` object containing the `id` of your recipient. If the `id` does not exist, Customer.io creates it.
|
189
|
+
* a `message_data` object containing properties that you want reference in your message using liquid.
|
190
|
+
* You can also send attachments with your message. Use `attach` to encode attachments.
|
193
191
|
|
194
|
-
|
192
|
+
Use `send_email` referencing your request to send a transactional message. [Learn more about transactional messages and `SendEmailRequest` properties](https://customer.io/docs/transactional-api).
|
195
193
|
|
196
|
-
Remove the list of customer ids from the specified manual segment.
|
197
194
|
|
198
195
|
```ruby
|
199
|
-
|
196
|
+
require "customerio"
|
197
|
+
|
198
|
+
client = Customerio::APIClient.new("your API key")
|
199
|
+
|
200
|
+
request = Customerio::SendEmailRequest.new(
|
201
|
+
to: "person@example.com",
|
202
|
+
transactional_message_id: "3",
|
203
|
+
message_data: {
|
204
|
+
name: "Person",
|
205
|
+
items: {
|
206
|
+
name: "shoes",
|
207
|
+
price: "59.99",
|
208
|
+
},
|
209
|
+
products: [],
|
210
|
+
},
|
211
|
+
identifiers: {
|
212
|
+
id: "2",
|
213
|
+
},
|
214
|
+
)
|
215
|
+
|
216
|
+
file = File.open('<file-path>', 'r')
|
217
|
+
request.attach("filename", file.read)
|
218
|
+
|
219
|
+
begin
|
220
|
+
response = client.send_email(request)
|
221
|
+
puts response
|
222
|
+
rescue Customerio::InvalidResponse => e
|
223
|
+
puts e.code, e.message
|
224
|
+
end
|
200
225
|
```
|
201
226
|
|
202
227
|
## Contributing
|
data/customerio.gemspec
CHANGED
@@ -17,10 +17,10 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.version = Customerio::VERSION
|
18
18
|
|
19
19
|
gem.add_dependency('multi_json', "~> 1.0")
|
20
|
+
gem.add_dependency('addressable', '~> 2.7.0')
|
20
21
|
|
21
22
|
gem.add_development_dependency('rake', '~> 10.5')
|
22
23
|
gem.add_development_dependency('rspec', '3.3.0')
|
23
|
-
gem.add_development_dependency('webmock', '
|
24
|
-
gem.add_development_dependency('addressable', '~> 2.3.6')
|
24
|
+
gem.add_development_dependency('webmock', '3.6.0')
|
25
25
|
gem.add_development_dependency('json')
|
26
26
|
end
|
data/lib/customerio.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
module Customerio
|
5
|
+
class APIClient
|
6
|
+
DEFAULT_API_URL = 'https://api.customer.io'
|
7
|
+
|
8
|
+
def initialize(app_key, options = {})
|
9
|
+
options[:url] = DEFAULT_API_URL if options[:url].nil? || options[:url].empty?
|
10
|
+
@client = Customerio::BaseClient.new({ app_key: app_key }, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_email(req)
|
14
|
+
raise "request must be an instance of Customerio::SendEmailRequest" unless req.is_a?(Customerio::SendEmailRequest)
|
15
|
+
response = @client.request(:post, send_email_path, req.message)
|
16
|
+
|
17
|
+
case response
|
18
|
+
when Net::HTTPSuccess then
|
19
|
+
JSON.parse(response.body)
|
20
|
+
when Net::HTTPBadRequest then
|
21
|
+
json = JSON.parse(response.body)
|
22
|
+
raise Customerio::InvalidResponse.new(response.code, json['meta']['error'], response)
|
23
|
+
else
|
24
|
+
raise InvalidResponse.new(response.code, response.body)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def send_email_path
|
31
|
+
"/v1/send/email"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
module Customerio
|
5
|
+
DEFAULT_TIMEOUT = 10
|
6
|
+
|
7
|
+
class InvalidRequest < RuntimeError; end
|
8
|
+
class InvalidResponse < RuntimeError
|
9
|
+
attr_reader :code, :response
|
10
|
+
|
11
|
+
def initialize(code, body, response=nil)
|
12
|
+
@message = body
|
13
|
+
@code = code
|
14
|
+
@response = response
|
15
|
+
|
16
|
+
super(@message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class BaseClient
|
21
|
+
def initialize(auth, options = {})
|
22
|
+
@auth = auth
|
23
|
+
@timeout = options[:timeout] || DEFAULT_TIMEOUT
|
24
|
+
@base_uri = options[:url]
|
25
|
+
end
|
26
|
+
|
27
|
+
def request(method, path, body = nil, headers = {})
|
28
|
+
execute(method, path, body, headers)
|
29
|
+
end
|
30
|
+
|
31
|
+
def request_and_verify_response(method, path, body = nil, headers = {})
|
32
|
+
verify_response(request(method, path, body, headers))
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def execute(method, path, body = nil, headers = {})
|
38
|
+
uri = URI.join(@base_uri, path)
|
39
|
+
|
40
|
+
session = Net::HTTP.new(uri.host, uri.port)
|
41
|
+
session.use_ssl = (uri.scheme == 'https')
|
42
|
+
session.open_timeout = @timeout
|
43
|
+
session.read_timeout = @timeout
|
44
|
+
|
45
|
+
req = request_class(method).new(uri.path)
|
46
|
+
|
47
|
+
if @auth.has_key?(:site_id) && @auth.has_key?(:api_key)
|
48
|
+
req.initialize_http_header(headers)
|
49
|
+
req.basic_auth @auth[:site_id], @auth[:api_key]
|
50
|
+
else
|
51
|
+
headers['Authorization'] = "Bearer #{@auth[:app_key]}"
|
52
|
+
req.initialize_http_header(headers)
|
53
|
+
end
|
54
|
+
|
55
|
+
if !body.nil?
|
56
|
+
req.add_field('Content-Type', 'application/json')
|
57
|
+
req.body = MultiJson.dump(body)
|
58
|
+
end
|
59
|
+
|
60
|
+
session.start do |http|
|
61
|
+
http.request(req)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_class(method)
|
66
|
+
case method
|
67
|
+
when :post
|
68
|
+
Net::HTTP::Post
|
69
|
+
when :put
|
70
|
+
Net::HTTP::Put
|
71
|
+
when :delete
|
72
|
+
Net::HTTP::Delete
|
73
|
+
else
|
74
|
+
raise InvalidRequest.new("Invalid request method #{method.inspect}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def verify_response(response)
|
79
|
+
case response
|
80
|
+
when Net::HTTPSuccess then
|
81
|
+
response
|
82
|
+
else
|
83
|
+
raise InvalidResponse.new(response.code, response.body, response)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/customerio/client.rb
CHANGED
@@ -1,29 +1,15 @@
|
|
1
|
-
require
|
2
|
-
require 'multi_json'
|
1
|
+
require "addressable/uri"
|
3
2
|
|
4
3
|
module Customerio
|
5
|
-
DEFAULT_BASE_URI = 'https://track.customer.io'
|
6
|
-
DEFAULT_TIMEOUT = 10
|
7
|
-
|
8
4
|
class Client
|
5
|
+
DEFAULT_TRACK_URL = 'https://track.customer.io'
|
6
|
+
|
9
7
|
class MissingIdAttributeError < RuntimeError; end
|
10
8
|
class ParamError < RuntimeError; end
|
11
|
-
class InvalidRequest < RuntimeError; end
|
12
|
-
class InvalidResponse < RuntimeError
|
13
|
-
attr_reader :response
|
14
|
-
|
15
|
-
def initialize(message, response)
|
16
|
-
super(message)
|
17
|
-
@response = response
|
18
|
-
end
|
19
|
-
end
|
20
9
|
|
21
|
-
def initialize(site_id,
|
22
|
-
|
23
|
-
@
|
24
|
-
@json = options.has_key?(:json) ? options[:json] : true
|
25
|
-
@base_uri = options[:base_uri] || DEFAULT_BASE_URI
|
26
|
-
@timeout = options[:timeout] || DEFAULT_TIMEOUT
|
10
|
+
def initialize(site_id, api_key, options = {})
|
11
|
+
options[:url] = DEFAULT_TRACK_URL if options[:url].nil? || options[:url].empty?
|
12
|
+
@client = Customerio::BaseClient.new({ site_id: site_id, api_key: api_key }, options)
|
27
13
|
end
|
28
14
|
|
29
15
|
def identify(attributes)
|
@@ -31,41 +17,36 @@ module Customerio
|
|
31
17
|
end
|
32
18
|
|
33
19
|
def delete(customer_id)
|
34
|
-
|
20
|
+
raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
|
21
|
+
@client.request_and_verify_response(:delete, customer_path(customer_id))
|
35
22
|
end
|
36
23
|
|
37
24
|
def suppress(customer_id)
|
38
|
-
|
25
|
+
raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
|
26
|
+
@client.request_and_verify_response(:post, suppress_path(customer_id))
|
39
27
|
end
|
40
28
|
|
41
29
|
def unsuppress(customer_id)
|
42
|
-
|
30
|
+
raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
|
31
|
+
@client.request_and_verify_response(:post, unsuppress_path(customer_id))
|
43
32
|
end
|
44
33
|
|
45
|
-
def track(
|
46
|
-
|
47
|
-
|
48
|
-
if args.length == 1
|
49
|
-
# Only passed in an event name, create an anonymous event
|
50
|
-
event_name = args.first
|
51
|
-
create_anonymous_event(event_name, attributes)
|
52
|
-
else
|
53
|
-
# Passed in a customer id and an event name.
|
54
|
-
# Track the event for the given customer
|
55
|
-
customer_id, event_name = args
|
34
|
+
def track(customer_id, event_name, attributes = {})
|
35
|
+
raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
|
36
|
+
raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name)
|
56
37
|
|
57
|
-
|
58
|
-
end
|
38
|
+
create_customer_event(customer_id, event_name, attributes)
|
59
39
|
end
|
60
40
|
|
61
41
|
def anonymous_track(event_name, attributes = {})
|
42
|
+
raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name)
|
62
43
|
create_anonymous_event(event_name, attributes)
|
63
44
|
end
|
64
45
|
|
65
46
|
def add_device(customer_id, device_id, platform, data={})
|
66
|
-
raise ParamError.new("customer_id must be a non-empty string")
|
67
|
-
raise ParamError.new("device_id must be a non-empty string")
|
68
|
-
raise ParamError.new("platform must be a non-empty string")
|
47
|
+
raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
|
48
|
+
raise ParamError.new("device_id must be a non-empty string") if is_empty?(device_id)
|
49
|
+
raise ParamError.new("platform must be a non-empty string") if is_empty?(platform)
|
69
50
|
|
70
51
|
if data.nil?
|
71
52
|
data = {}
|
@@ -73,69 +54,54 @@ module Customerio
|
|
73
54
|
|
74
55
|
raise ParamError.new("data parameter must be a hash") unless data.is_a?(Hash)
|
75
56
|
|
76
|
-
|
57
|
+
@client.request_and_verify_response(:put, device_path(customer_id), {
|
77
58
|
:device => data.update({
|
78
59
|
:id => device_id,
|
79
60
|
:platform => platform,
|
80
61
|
})
|
81
|
-
})
|
62
|
+
})
|
82
63
|
end
|
83
64
|
|
84
65
|
def delete_device(customer_id, device_id)
|
85
|
-
raise ParamError.new("customer_id must be a non-empty string")
|
86
|
-
raise ParamError.new("device_id must be a non-empty string")
|
87
|
-
|
88
|
-
verify_response(request(:delete, device_id_path(customer_id, device_id)))
|
89
|
-
end
|
90
|
-
|
91
|
-
def add_to_segment(segment_id, customer_ids)
|
92
|
-
raise ParamError.new("segment_id must be an integer") unless segment_id.is_a? Integer
|
93
|
-
raise ParamError.new("customer_ids must be a list of values") unless customer_ids.is_a? Array
|
66
|
+
raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
|
67
|
+
raise ParamError.new("device_id must be a non-empty string") if is_empty?(device_id)
|
94
68
|
|
95
|
-
|
96
|
-
|
97
|
-
verify_response(request(:post, add_to_segment_path(segment_id), {
|
98
|
-
:ids => customer_ids,
|
99
|
-
}))
|
69
|
+
@client.request_and_verify_response(:delete, device_id_path(customer_id, device_id))
|
100
70
|
end
|
101
71
|
|
102
|
-
|
103
|
-
raise ParamError.new("segment_id must be an integer") unless segment_id.is_a? Integer
|
104
|
-
raise ParamError.new("customer_ids must be a list of values") unless customer_ids.is_a? Array
|
72
|
+
private
|
105
73
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
:ids => customer_ids,
|
110
|
-
}))
|
74
|
+
def escape(val)
|
75
|
+
# CGI.escape is recommended for escaping, however, it doesn't correctly escape spaces.
|
76
|
+
Addressable::URI.encode_component(val.to_s, Addressable::URI::CharacterClasses::UNRESERVED)
|
111
77
|
end
|
112
78
|
|
113
|
-
|
79
|
+
def device_path(customer_id)
|
80
|
+
"/api/v1/customers/#{escape(customer_id)}/devices"
|
81
|
+
end
|
114
82
|
|
115
|
-
def
|
116
|
-
"/api/v1/
|
83
|
+
def device_id_path(customer_id, device_id)
|
84
|
+
"/api/v1/customers/#{escape(customer_id)}/devices/#{escape(device_id)}"
|
117
85
|
end
|
118
86
|
|
119
|
-
def
|
120
|
-
"/api/v1/
|
87
|
+
def customer_path(id)
|
88
|
+
"/api/v1/customers/#{escape(id)}"
|
121
89
|
end
|
122
90
|
|
123
|
-
def
|
124
|
-
"/api/v1/customers/#{customer_id}/
|
91
|
+
def suppress_path(customer_id)
|
92
|
+
"/api/v1/customers/#{escape(customer_id)}/suppress"
|
125
93
|
end
|
126
94
|
|
127
|
-
def
|
128
|
-
"/api/v1/customers/#{customer_id}/
|
95
|
+
def unsuppress_path(customer_id)
|
96
|
+
"/api/v1/customers/#{escape(customer_id)}/unsuppress"
|
129
97
|
end
|
130
98
|
|
131
99
|
def create_or_update(attributes = {})
|
132
100
|
attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
|
133
|
-
|
134
|
-
raise MissingIdAttributeError.new("Must provide a customer id") unless attributes[:id]
|
101
|
+
raise MissingIdAttributeError.new("Must provide a customer id") if is_empty?(attributes[:id])
|
135
102
|
|
136
103
|
url = customer_path(attributes[:id])
|
137
|
-
|
138
|
-
verify_response(request(:put, url, attributes))
|
104
|
+
@client.request_and_verify_response(:put, url, attributes)
|
139
105
|
end
|
140
106
|
|
141
107
|
def create_customer_event(customer_id, event_name, attributes = {})
|
@@ -149,79 +115,15 @@ module Customerio
|
|
149
115
|
def create_event(url, event_name, attributes = {})
|
150
116
|
body = { :name => event_name, :data => attributes }
|
151
117
|
body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp])
|
152
|
-
|
153
|
-
end
|
154
|
-
|
155
|
-
def customer_path(id)
|
156
|
-
"/api/v1/customers/#{id}"
|
157
|
-
end
|
158
|
-
|
159
|
-
def suppress_path(customer_id)
|
160
|
-
"/api/v1/customers/#{customer_id}/suppress"
|
161
|
-
end
|
162
|
-
|
163
|
-
def unsuppress_path(customer_id)
|
164
|
-
"/api/v1/customers/#{customer_id}/unsuppress"
|
118
|
+
@client.request_and_verify_response(:post, url, body)
|
165
119
|
end
|
166
120
|
|
167
121
|
def valid_timestamp?(timestamp)
|
168
122
|
timestamp && timestamp.is_a?(Integer) && timestamp > 999999999 && timestamp < 100000000000
|
169
123
|
end
|
170
124
|
|
171
|
-
|
172
|
-
|
173
|
-
if response.code.to_i >= 200 && response.code.to_i < 300
|
174
|
-
response
|
175
|
-
else
|
176
|
-
raise InvalidResponse.new("Customer.io API returned an invalid response: #{response.code}", response)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def extract_attributes(args)
|
181
|
-
hash = args.last.is_a?(Hash) ? args.pop : {}
|
182
|
-
hash.inject({}){ |hash, (k,v)| hash[k.to_sym] = v; hash }
|
183
|
-
end
|
184
|
-
|
185
|
-
def request(method, path, body = nil, headers = {})
|
186
|
-
uri = URI.join(@base_uri, path)
|
187
|
-
|
188
|
-
session = Net::HTTP.new(uri.host, uri.port)
|
189
|
-
session.use_ssl = (uri.scheme == 'https')
|
190
|
-
session.open_timeout = @timeout
|
191
|
-
session.read_timeout = @timeout
|
192
|
-
|
193
|
-
req = request_class(method).new(uri.path)
|
194
|
-
req.initialize_http_header(headers)
|
195
|
-
req.basic_auth @username, @password
|
196
|
-
|
197
|
-
add_request_body(req, body) unless body.nil?
|
198
|
-
|
199
|
-
session.start do |http|
|
200
|
-
http.request(req)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def request_class(method)
|
205
|
-
case method
|
206
|
-
when :post
|
207
|
-
Net::HTTP::Post
|
208
|
-
when :put
|
209
|
-
Net::HTTP::Put
|
210
|
-
when :delete
|
211
|
-
Net::HTTP::Delete
|
212
|
-
else
|
213
|
-
raise InvalidRequest.new("Invalid request method #{method.inspect}")
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def add_request_body(req, body)
|
218
|
-
if @json
|
219
|
-
req.add_field('Content-Type', 'application/json')
|
220
|
-
req.body = MultiJson.dump(body)
|
221
|
-
else
|
222
|
-
req.add_field('Content-Type', 'application/x-www-form-urlencoded')
|
223
|
-
req.body = ParamEncoder.to_params(body)
|
224
|
-
end
|
125
|
+
def is_empty?(val)
|
126
|
+
val.nil? || (val.is_a?(String) && val.strip == "")
|
225
127
|
end
|
226
128
|
end
|
227
129
|
end
|