exact_target_sdk 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +6 -0
- data/LICENSE.txt +7 -0
- data/README.rdoc +36 -0
- data/lib/exact_target_sdk.rb +14 -0
- data/lib/exact_target_sdk/api_object.rb +147 -0
- data/lib/exact_target_sdk/client.rb +140 -0
- data/lib/exact_target_sdk/config.rb +61 -0
- data/lib/exact_target_sdk/create_response.rb +17 -0
- data/lib/exact_target_sdk/create_result.rb +12 -0
- data/lib/exact_target_sdk/errors.rb +35 -0
- data/lib/exact_target_sdk/subscriber.rb +31 -0
- data/lib/exact_target_sdk/triggered_send.rb +8 -0
- data/lib/exact_target_sdk/triggered_send_definition.rb +7 -0
- data/lib/exact_target_sdk/version.rb +3 -0
- metadata +125 -0
data/CHANGELOG.rdoc
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2012 RevPAR Collective, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
= ExactTarget SDK
|
2
|
+
|
3
|
+
An object-oriented wrapper for the ExactTarget SOAP API.
|
4
|
+
|
5
|
+
The ExactTarget web service guide can be viewed here:
|
6
|
+
http://docs.code.exacttarget.com/020_Web_Service_Guide
|
7
|
+
|
8
|
+
With few exceptions, ruby conventions for capitalization are ignored and those
|
9
|
+
outlined in the guide linked above are used. This is done in an attempt to be
|
10
|
+
as transparent as possible, so that the API may be used by referring only to
|
11
|
+
the guide linked above.
|
12
|
+
|
13
|
+
Note this SDK is currently very incomplete, allowing you only to create
|
14
|
+
subscribers and trigger sends. The framework is in place, however, to very
|
15
|
+
easily implement new objects by simply declaring their properties.
|
16
|
+
|
17
|
+
== Synopsis:
|
18
|
+
|
19
|
+
ExactTargetSDK.config(:username => 'foo', :password => 'mypass')
|
20
|
+
|
21
|
+
client = ExactTargetSDK::Client.new
|
22
|
+
definition = TriggeredSendDefinition.new('CustomerKey' => 'my_triggered_send')
|
23
|
+
subscriber = Subscriber.new('EmailAddress' => 'me@example.com')
|
24
|
+
triggered_send = TriggeredSend.new('TriggeredSendDefinition' => definition)
|
25
|
+
triggered_send.subscribers << subscriber
|
26
|
+
|
27
|
+
# Creates subscriber record, then executes the "my_triggered_send" trigger to
|
28
|
+
# that subscriber.
|
29
|
+
response = client.Create(subscriber, triggered_send)
|
30
|
+
|
31
|
+
puts "response status: #{response.OverallStatus}"
|
32
|
+
response.Results.each do |result|
|
33
|
+
puts "result..."
|
34
|
+
puts " result code: #{result.StatusCode}"
|
35
|
+
puts " result message: #{result.StatusMessage}"
|
36
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'exact_target_sdk/config'
|
2
|
+
require 'exact_target_sdk/errors'
|
3
|
+
|
4
|
+
module ExactTargetSDK
|
5
|
+
|
6
|
+
autoload :APIObject, 'exact_target_sdk/api_object'
|
7
|
+
autoload :Client, 'exact_target_sdk/client'
|
8
|
+
autoload :CreateResponse, 'exact_target_sdk/create_response'
|
9
|
+
autoload :CreateResult, 'exact_target_sdk/create_result'
|
10
|
+
autoload :Subscriber, 'exact_target_sdk/subscriber'
|
11
|
+
autoload :TriggeredSend, 'exact_target_sdk/triggered_send'
|
12
|
+
autoload :TriggeredSendDefinition, 'exact_target_sdk/triggered_send_definition'
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module ExactTargetSDK
|
4
|
+
|
5
|
+
# Parent class of all ExactTarget API objects (listed here:
|
6
|
+
# http://docs.code.exacttarget.com/020_Web_Service_Guide/Objects). Provides
|
7
|
+
# class-level declarations, validation, and rendering that makes modeling
|
8
|
+
# each object easy.
|
9
|
+
class APIObject
|
10
|
+
|
11
|
+
include ::ActiveModel::Validations
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
# Declares a property of this object, optionally requiring it upon
|
16
|
+
# validation.
|
17
|
+
#
|
18
|
+
# Provides a getter and setter for this property, keeping track of
|
19
|
+
# whether or not it has been set and registering it for rendering.
|
20
|
+
def property(name, required = false)
|
21
|
+
name = name.to_s
|
22
|
+
attr_reader name.to_sym
|
23
|
+
class_eval <<-__EOF__
|
24
|
+
def #{name}=(value)
|
25
|
+
@_set_#{name} = true
|
26
|
+
@#{name} = value
|
27
|
+
end
|
28
|
+
__EOF__
|
29
|
+
if required
|
30
|
+
validates name.to_sym, :presence => true
|
31
|
+
end
|
32
|
+
register_property!(name)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Declares a property as an array of values.
|
36
|
+
#
|
37
|
+
# Provides a getter and setter for this property. The getter will
|
38
|
+
# always return an array (not null), so the client may simply append
|
39
|
+
# to this property.
|
40
|
+
#
|
41
|
+
# Note that once the property has been either read or written to, it
|
42
|
+
# will be rendered.
|
43
|
+
def array_property(name)
|
44
|
+
# TODO: type validation would be nice
|
45
|
+
name = name.to_s
|
46
|
+
class_eval <<-__EOF__
|
47
|
+
def #{name}
|
48
|
+
@_set_#{name} = true
|
49
|
+
@#{name} ||= []
|
50
|
+
end
|
51
|
+
def #{name}=(value)
|
52
|
+
@_set_#{name} = true
|
53
|
+
@#{name} = value
|
54
|
+
end
|
55
|
+
__EOF__
|
56
|
+
register_property!(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Same as #property, adding validation the the provided value is an
|
60
|
+
# integer.
|
61
|
+
def int_property(name, required = false)
|
62
|
+
property(name, required)
|
63
|
+
validates name.to_sym, :numericality => { :allow_nil => true, :only_integer => true }
|
64
|
+
end
|
65
|
+
|
66
|
+
# Takes one or more method names as symbols, and executes them in order
|
67
|
+
# before validation occurs on this object.
|
68
|
+
def before_validation(*args)
|
69
|
+
before_validation_methods.concat(args)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns an array of all registered properties.
|
73
|
+
def properties
|
74
|
+
@properties || []
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Returns the method names declared using #before_validation.
|
80
|
+
def before_validation_methods
|
81
|
+
@before_validation_methods ||= []
|
82
|
+
end
|
83
|
+
|
84
|
+
# Stores the given property name to be used at render time.
|
85
|
+
def register_property!(name)
|
86
|
+
@properties ||= []
|
87
|
+
@properties << name
|
88
|
+
@properties.uniq!
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# By default, any properties may be passed and set.
|
94
|
+
#
|
95
|
+
# May be overridden.
|
96
|
+
def initialize(properties = {})
|
97
|
+
properties.each do |key, value|
|
98
|
+
self.send "#{key}=", value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# By default, returns the name of the class.
|
103
|
+
#
|
104
|
+
# May be overridden.
|
105
|
+
def type_name
|
106
|
+
self.class.name.split('::').last
|
107
|
+
end
|
108
|
+
|
109
|
+
# By default, runs validation and executes #render_properties!.
|
110
|
+
#
|
111
|
+
# If overridden, the child class should execute the before_validation
|
112
|
+
# methods, check wehter or not the object is valid, and then render
|
113
|
+
# the object.
|
114
|
+
def render!(xml)
|
115
|
+
self.class.before_validation_methods.each { |method| self.send(method) }
|
116
|
+
raise(InvalidAPIObject, self) if invalid?
|
117
|
+
render_properties!(xml)
|
118
|
+
end
|
119
|
+
|
120
|
+
# By default, loops through all registered properties, and renders
|
121
|
+
# each that has been explicitly set.
|
122
|
+
#
|
123
|
+
# May be overridden.
|
124
|
+
def render_properties!(xml)
|
125
|
+
self.class.properties.each do |property|
|
126
|
+
next unless instance_variable_get("@_set_#{property}")
|
127
|
+
|
128
|
+
property_value = self.send(property)
|
129
|
+
|
130
|
+
if property_value.is_a?(APIObject)
|
131
|
+
xml.__send__(property) do
|
132
|
+
property_value.render!(xml)
|
133
|
+
end
|
134
|
+
elsif property_value.is_a?(Array)
|
135
|
+
property_value.each do |current|
|
136
|
+
xml.__send__(property) do
|
137
|
+
current.render!(xml)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
else
|
141
|
+
xml.__send__(property, property_value)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'guid'
|
2
|
+
require 'savon'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module ExactTargetSDK
|
6
|
+
|
7
|
+
# Provides an object-oriented API to ExactTarget's Web Service API
|
8
|
+
# (http://docs.code.exacttarget.com/020_Web_Service_Guide)
|
9
|
+
#
|
10
|
+
# With few exceptions, ruby conventions for capitalization are ignored and those
|
11
|
+
# outlined in the guide linked above are used. This is done in an attempt to be
|
12
|
+
# as transparent as possible, so that the API may be used by referring only to
|
13
|
+
# the guide linked above.
|
14
|
+
class Client
|
15
|
+
|
16
|
+
# Constructs a client.
|
17
|
+
#
|
18
|
+
# Any of the options documented in ExactTargetSDK#config may be overridden
|
19
|
+
# using the options parameter.
|
20
|
+
#
|
21
|
+
# Since ExactTarget's API is stateless, constructing a client object will not
|
22
|
+
# make any remote calls.
|
23
|
+
def initialize(options = {})
|
24
|
+
self.config = {
|
25
|
+
}.merge!(ExactTargetSDK.config).merge!(options)
|
26
|
+
|
27
|
+
Savon.configure do |c|
|
28
|
+
c.logger = config[:logger]
|
29
|
+
c.raise_errors = false
|
30
|
+
end
|
31
|
+
|
32
|
+
initialize_client!
|
33
|
+
end
|
34
|
+
|
35
|
+
# Invokes the Create method.
|
36
|
+
#
|
37
|
+
# The provided arguments should each be sub-classes of APIObject, and each
|
38
|
+
# provided object will be created in order.
|
39
|
+
#
|
40
|
+
# Possible exceptions are:
|
41
|
+
# HTTPError if an HTTP error (such as a timeout) occurs
|
42
|
+
# SOAPFault if a SOAP fault occurs
|
43
|
+
# Timeout if there is a timeout waiting for the response
|
44
|
+
# InvalidAPIObject if any of the provided objects don't pass validation
|
45
|
+
#
|
46
|
+
# Returns a CreateResponse object.
|
47
|
+
def Create(*args)
|
48
|
+
# TODO: implement and accept CreateOptions
|
49
|
+
|
50
|
+
api_objects = args
|
51
|
+
|
52
|
+
response = execute_request 'Create' do |xml|
|
53
|
+
xml.CreateRequest do
|
54
|
+
xml.Options # TODO: support CreateOptions
|
55
|
+
|
56
|
+
api_objects.each do |api_object|
|
57
|
+
xml.Objects "xsi:type" => api_object.type_name do
|
58
|
+
api_object.render!(xml)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
CreateResponse.new(response)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
attr_accessor :config, :client
|
70
|
+
|
71
|
+
# Constructs and saves the savon client using provided config.
|
72
|
+
def initialize_client!
|
73
|
+
self.client = ::Savon::Client.new do
|
74
|
+
wsdl.endpoint = config[:endpoint]
|
75
|
+
wsdl.namespace = config[:namespace]
|
76
|
+
http.open_timeout = config[:open_timeout]
|
77
|
+
http.read_timeout = config[:read_timeout]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Builds the SOAP request for the given method, delegating body
|
82
|
+
# rendering to the provided block.
|
83
|
+
#
|
84
|
+
# Handles errors and re-raises with appropriate sub-class of
|
85
|
+
# ExactTargetSDK::Error.
|
86
|
+
#
|
87
|
+
# Returns the raw savon response.
|
88
|
+
def execute_request(method)
|
89
|
+
begin
|
90
|
+
response = client.request(method) do
|
91
|
+
soap.xml do |xml|
|
92
|
+
xml.s :Envelope,
|
93
|
+
"xmlns" => config[:namespace],
|
94
|
+
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
|
95
|
+
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
96
|
+
"xmlns:s" => "http://www.w3.org/2003/05/soap-envelope",
|
97
|
+
"xmlns:a" => "http://schemas.xmlsoap.org/ws/2004/08/addressing",
|
98
|
+
"xmlns:o" => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" do
|
99
|
+
|
100
|
+
xml.s :Header do
|
101
|
+
xml.a :Action, method, "s:mustUnderstand" => "1"
|
102
|
+
xml.a :MessageID, "uuid:#{Guid.new.to_s}"
|
103
|
+
xml.a :ReplyTo do
|
104
|
+
xml.a :Address, "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"
|
105
|
+
end
|
106
|
+
xml.a :To, config[:endpoint], "s:mustUnderstand" => "1"
|
107
|
+
xml.o :Security, "s:mustUnderstand" => "1" do
|
108
|
+
xml.o :UsernameToken, "o:Id" => "test" do
|
109
|
+
xml.o :Username, config[:username]
|
110
|
+
xml.o :Password, config[:password]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
xml.s :Body do
|
116
|
+
yield(xml)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if response.http_error?
|
123
|
+
raise HTTPError, response.http_error.to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
if response.soap_fault?
|
127
|
+
raise SOAPFault, response.soap_fault.to_s
|
128
|
+
end
|
129
|
+
|
130
|
+
response
|
131
|
+
rescue Timeout::Error => e
|
132
|
+
timeout = ::ExactTargetSDK::Timeout.new("#{e.message}; open_timeout: #{config[:open_timeout]}; read_timeout: #{config[:read_timeout]}")
|
133
|
+
timeout.set_backtrace(e.backtrace)
|
134
|
+
raise timeout
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module ExactTargetSDK
|
4
|
+
|
5
|
+
DEFAULT_TIMEOUT = 15
|
6
|
+
DEFAULT_ENDPOINT = 'https://webservice.s4.exacttarget.com/Service.asmx'
|
7
|
+
DEFAULT_NAMESPACE = 'http://exacttarget.com/wsdl/partnerAPI'
|
8
|
+
|
9
|
+
# Globally configures and retrieves configuration for the ExactTarget SDK.
|
10
|
+
#
|
11
|
+
# == Environment Variables
|
12
|
+
#
|
13
|
+
# For convenience in a command-line environment, configuration may be skipped
|
14
|
+
# by setting the EXACT_TARGET_SDK_USERNAME and EXACT_TARGET_SDK_PASSWORD
|
15
|
+
# environment variables, which are self-explanatory.
|
16
|
+
#
|
17
|
+
# == Rails
|
18
|
+
#
|
19
|
+
# If running in a rails environment, this configuration will automatically use
|
20
|
+
# the global Rails.logger instance. This behavior may be overridden by passing
|
21
|
+
# in a :logger option.
|
22
|
+
#
|
23
|
+
# @param [Hash] options
|
24
|
+
# @option options [String] :username (nil) ExactTarget account username
|
25
|
+
# @option options [String] :password (nil) ExactTarget account password
|
26
|
+
# @option options [Logger] :logger (Rails.logger) Logger to use
|
27
|
+
# @option options [Numeric] :open_timeout (ExactTargetSDK::DEFAULT_TIMEOUT)
|
28
|
+
# Number of seconds to wait for the connection to open
|
29
|
+
# (see Net::HTTP#open_timeout)
|
30
|
+
# @option options [Numeric] :read_timeout (ExactTargetSDK::DEFAULT_TIMEOUT)
|
31
|
+
# Number of seconds to wait for one block to be read
|
32
|
+
# (see Net::HTTP#read_timeout)
|
33
|
+
def self.config(options = nil)
|
34
|
+
@config ||= {
|
35
|
+
:username => ENV['EXACT_TARGET_SDK_USERNAME'],
|
36
|
+
:password => ENV['EXACT_TARGET_SDK_PASSWORD'],
|
37
|
+
:logger => default_logger,
|
38
|
+
:open_timeout => DEFAULT_TIMEOUT,
|
39
|
+
:read_timeout => DEFAULT_TIMEOUT,
|
40
|
+
:endpoint => DEFAULT_ENDPOINT,
|
41
|
+
:namespace => DEFAULT_NAMESPACE,
|
42
|
+
}
|
43
|
+
|
44
|
+
@config.merge!(options) if options
|
45
|
+
|
46
|
+
@config
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def self.default_logger
|
52
|
+
if defined?(::Rails)
|
53
|
+
::Rails.logger
|
54
|
+
else
|
55
|
+
logger = ::Logger.new(STDERR)
|
56
|
+
logger.level = ::Logger::INFO
|
57
|
+
logger
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ExactTargetSDK
|
2
|
+
class CreateResponse
|
3
|
+
|
4
|
+
attr_reader :OverallStatus, :RequestID, :Results
|
5
|
+
|
6
|
+
def initialize(response)
|
7
|
+
response = response.to_hash[:create_response]
|
8
|
+
@OverallStatus = response[:overall_status]
|
9
|
+
@RequestID = response[:request_id]
|
10
|
+
@Results = []
|
11
|
+
(response[:results] || []).each do |result|
|
12
|
+
@Results << CreateResult.new(result)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ExactTargetSDK
|
2
|
+
|
3
|
+
# Parent of all errors raised by this SDK
|
4
|
+
class Error < ::StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
# Indicates an "HTTP error" as defined by savon
|
8
|
+
class HTTPError < Error
|
9
|
+
end
|
10
|
+
|
11
|
+
# Indicates a "SOAP fault" as defined by savon
|
12
|
+
class SOAPFault < Error
|
13
|
+
end
|
14
|
+
|
15
|
+
# Indicates the open or read timeouts were reached
|
16
|
+
class Timeout < Error
|
17
|
+
end
|
18
|
+
|
19
|
+
# Indicates validation failed on an APIObject, which is referenced
|
20
|
+
# in the exception.
|
21
|
+
class InvalidAPIObject < Error
|
22
|
+
|
23
|
+
attr_reader :api_object
|
24
|
+
|
25
|
+
def initialize(api_object)
|
26
|
+
@api_object = api_object
|
27
|
+
end
|
28
|
+
|
29
|
+
def message
|
30
|
+
"#{api_object.type_name} object is invalid: #{api_object.errors.full_messages.join('; ')}"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ExactTargetSDK
|
2
|
+
|
3
|
+
# Assumes that the "SubscriberKey feature" is not enabled on your account, and
|
4
|
+
# thus explicitly sets the SubscriberKey to be the same as the EmailAddress
|
5
|
+
# (and vice-versa). This allows all methods to be used without ever needing to
|
6
|
+
# refer to the SubscriberKey (just use EmailAddress).
|
7
|
+
#
|
8
|
+
# If the SubscriberKey is explicitly set, it will be left alone (in case you do
|
9
|
+
# have the SubscriberKey feature enabled).
|
10
|
+
#
|
11
|
+
# When updating, the email address may be updated by setting the SubscriberKey
|
12
|
+
# property to the current email address, and the EmailAddress property to the
|
13
|
+
# new email address.
|
14
|
+
class Subscriber < APIObject
|
15
|
+
|
16
|
+
property 'SubscriberKey', true
|
17
|
+
property 'EmailAddress', true
|
18
|
+
array_property 'Attributes'
|
19
|
+
|
20
|
+
before_validation :sync_subscriber_key_and_email_address
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def sync_subscriber_key_and_email_address
|
25
|
+
self.SubscriberKey = self.EmailAddress if self.SubscriberKey.nil?
|
26
|
+
self.EmailAddress = self.SubscriberKey if self.EmailAddress.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: exact_target_sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 0.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- David Dawson
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-01-30 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
22
|
+
none: false
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
hash: 5
|
27
|
+
segments:
|
28
|
+
- 3
|
29
|
+
- 1
|
30
|
+
version: "3.1"
|
31
|
+
version_requirements: *id001
|
32
|
+
name: activemodel
|
33
|
+
prerelease: false
|
34
|
+
type: :runtime
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
hash: 9
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
- 1
|
45
|
+
version: "0.1"
|
46
|
+
version_requirements: *id002
|
47
|
+
name: guid
|
48
|
+
prerelease: false
|
49
|
+
type: :runtime
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 25
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
- 9
|
60
|
+
version: "0.9"
|
61
|
+
version_requirements: *id003
|
62
|
+
name: savon
|
63
|
+
prerelease: false
|
64
|
+
type: :runtime
|
65
|
+
description: Provides an easy-to-use ruby interface into the ExactTarget SOAP API, using the Savon client.
|
66
|
+
email: daws23@gmail.com
|
67
|
+
executables: []
|
68
|
+
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files:
|
72
|
+
- README.rdoc
|
73
|
+
- CHANGELOG.rdoc
|
74
|
+
- LICENSE.txt
|
75
|
+
files:
|
76
|
+
- lib/exact_target_sdk/api_object.rb
|
77
|
+
- lib/exact_target_sdk/client.rb
|
78
|
+
- lib/exact_target_sdk/config.rb
|
79
|
+
- lib/exact_target_sdk/create_response.rb
|
80
|
+
- lib/exact_target_sdk/create_result.rb
|
81
|
+
- lib/exact_target_sdk/errors.rb
|
82
|
+
- lib/exact_target_sdk/subscriber.rb
|
83
|
+
- lib/exact_target_sdk/triggered_send.rb
|
84
|
+
- lib/exact_target_sdk/triggered_send_definition.rb
|
85
|
+
- lib/exact_target_sdk/version.rb
|
86
|
+
- lib/exact_target_sdk.rb
|
87
|
+
- README.rdoc
|
88
|
+
- CHANGELOG.rdoc
|
89
|
+
- LICENSE.txt
|
90
|
+
homepage: https://github.com/daws/exact_target_sdk
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options:
|
95
|
+
- --main
|
96
|
+
- README.rdoc
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
hash: 3
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
version: "0"
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
hash: 3
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
version: "0"
|
117
|
+
requirements: []
|
118
|
+
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 1.8.10
|
121
|
+
signing_key:
|
122
|
+
specification_version: 3
|
123
|
+
summary: A simple wrapper for the ExactTarget SOAP API.
|
124
|
+
test_files: []
|
125
|
+
|