mosaic-lyris 1.0.1
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.
- data/Gemfile +3 -0
- data/README +4 -0
- data/Rakefile +31 -0
- data/VERSION +1 -0
- data/init.rb +4 -0
- data/lib/lyris.rb +2 -0
- data/lib/mosaic/lyris.rb +12 -0
- data/lib/mosaic/lyris/demographic.rb +65 -0
- data/lib/mosaic/lyris/filter.rb +6 -0
- data/lib/mosaic/lyris/list.rb +73 -0
- data/lib/mosaic/lyris/message.rb +95 -0
- data/lib/mosaic/lyris/object.rb +227 -0
- data/lib/mosaic/lyris/partner.rb +6 -0
- data/lib/mosaic/lyris/record.rb +101 -0
- data/lib/mosaic/lyris/trigger.rb +113 -0
- data/lib/mosaic/lyris/upload.rb +89 -0
- data/lib/mosaic/lyris_mailer.rb +102 -0
- data/mosaic-lyris.gemspec +143 -0
- data/test/demographic_test.rb +176 -0
- data/test/filter_test.rb +6 -0
- data/test/http_responder.rb +88 -0
- data/test/list_test.rb +49 -0
- data/test/message_test.rb +6 -0
- data/test/partner_test.rb +6 -0
- data/test/record_test.rb +177 -0
- data/test/responses/demographic/add_error_name_already_exists.xml +2 -0
- data/test/responses/demographic/add_success_12345.xml +2 -0
- data/test/responses/demographic/query_all_success.xml +19 -0
- data/test/responses/demographic/query_enabled_details_success.xml +12 -0
- data/test/responses/demographic/query_enabled_success.xml +13 -0
- data/test/responses/list/add_error_name_already_exists.xml +2 -0
- data/test/responses/list/add_success_12345.xml +2 -0
- data/test/responses/list/delete_error_not_found_99999.xml +2 -0
- data/test/responses/list/delete_success_12345.xml +2 -0
- data/test/responses/list/query_list_data_success.xml +20 -0
- data/test/responses/record/add_error_email_already_exists.xml +2 -0
- data/test/responses/record/add_success.xml +2 -0
- data/test/responses/record/query_all_success.xml +94 -0
- data/test/responses/record/query_all_success_empty.xml +2 -0
- data/test/responses/record/query_all_success_page_1.xml +54 -0
- data/test/responses/record/query_all_success_page_2.xml +34 -0
- data/test/responses/record/query_all_success_page_3.xml +14 -0
- data/test/responses/record/query_email_error_not_found.xml +2 -0
- data/test/responses/record/query_email_success_active.xml +14 -0
- data/test/responses/record/query_email_success_admin_trashed.xml +14 -0
- data/test/responses/record/query_email_success_bounced.xml +14 -0
- data/test/responses/record/query_email_success_unsubscribed.xml +14 -0
- data/test/responses/record/update_error_not_found.xml +2 -0
- data/test/responses/record/update_success.xml +2 -0
- data/test/responses/triggers/fire_error_invalid_recipients.xml +2 -0
- data/test/responses/triggers/fire_error_invalid_trigger_id.xml +2 -0
- data/test/responses/triggers/fire_success.xml +2 -0
- data/test/test_helper.rb +68 -0
- data/test/trigger_test.rb +45 -0
- metadata +342 -0
data/Gemfile
ADDED
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
task :default => [:test]
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.pattern = 'test/*_test.rb'
|
8
|
+
t.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
Rake::Task[:test].comment = "Run all tests"
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gemspec|
|
16
|
+
gemspec.name = "mosaic-lyris"
|
17
|
+
gemspec.summary = "Lyris/EmailLabs API"
|
18
|
+
gemspec.description = "A wrapper for the Lyris/EmailLabs API to simplify integration"
|
19
|
+
gemspec.email = "brent.faulkner@mosaic.com"
|
20
|
+
gemspec.homepage = "http://github.com/mosaicxm/mosaic-lyris"
|
21
|
+
gemspec.authors = ["S. Brent Faulkner"]
|
22
|
+
gemspec.add_dependency('builder')
|
23
|
+
gemspec.add_dependency('active_support')
|
24
|
+
gemspec.add_dependency('htmlentities')
|
25
|
+
gemspec.add_dependency('nokogiri')
|
26
|
+
gemspec.add_dependency('tzinfo')
|
27
|
+
gemspec.add_development_dependency('mocha')
|
28
|
+
end
|
29
|
+
rescue LoadError
|
30
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
31
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.1
|
data/init.rb
ADDED
data/lib/lyris.rb
ADDED
data/lib/mosaic/lyris.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Mosaic
|
2
|
+
module Lyris
|
3
|
+
class Demographic < Object
|
4
|
+
attr_reader :enabled,
|
5
|
+
:group,
|
6
|
+
:id,
|
7
|
+
:list_id,
|
8
|
+
:name,
|
9
|
+
:options,
|
10
|
+
:size,
|
11
|
+
:type
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def add(type, name, options = {})
|
15
|
+
validate_options!(type, options)
|
16
|
+
reply = post('demographic', 'add') do |request|
|
17
|
+
request.MLID options[:list_id] if options[:list_id]
|
18
|
+
put_data(request, demographic_type(type), name)
|
19
|
+
put_array_data(request, 'option', options[:option])
|
20
|
+
put_data(request, 'state', 'enabled') if options[:enabled]
|
21
|
+
put_data(request, 'size', options[:size]) if options[:size]
|
22
|
+
end
|
23
|
+
new(options.merge(:id => reply.at('/DATASET/DATA').inner_html.to_i, :name => name, :type => type))
|
24
|
+
end
|
25
|
+
|
26
|
+
def query(what, options = {})
|
27
|
+
reply = post('demographic', query_type(what)) do |request|
|
28
|
+
request.MLID options[:list_id] if options[:list_id]
|
29
|
+
end
|
30
|
+
reply.search('/DATASET/RECORD').collect do |record|
|
31
|
+
new :enabled => ([:enabled, :enabled_details].include?(what) || get_boolean_data(record, 'state', 'enabled')),
|
32
|
+
:group => get_data(record, "group"),
|
33
|
+
:id => get_integer_data(record, 'id'),
|
34
|
+
:list_id => options[:list_id],
|
35
|
+
:name => get_data(record, 'name'),
|
36
|
+
:options => get_array_data(record, 'option'),
|
37
|
+
:size => get_integer_data(record, 'size'),
|
38
|
+
:type => get_data(record, 'type').downcase.gsub(/ /,'_').to_sym
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
def demographic_type(type)
|
44
|
+
raise ArgumentError, "expected :checkbox, :date, :multiple_checkbox, :multiple_select_list, :radio_button, :select_list, :text or :textarea; got #{type.inspect}" unless %w(checkbox date multiple_checkbox multiple_select_list radio_button select_list text textarea).include?(type.to_s)
|
45
|
+
type.to_s.gsub(/_/,' ')
|
46
|
+
end
|
47
|
+
|
48
|
+
def query_type(what)
|
49
|
+
raise ArgumentError, "expected :all, :enabled or :enabled_details; got #{what.inspect}" unless %w(all enabled enabled_details).include?(what.to_s)
|
50
|
+
"query-#{what}".gsub(/_/,'-')
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_options!(type, options)
|
54
|
+
if %w(multiple_checkbox multiple_select_list radio_button select_list).include?(type.to_s)
|
55
|
+
raise ArgumentError, "missing options for #{type.inspect} demographic" unless options[:options]
|
56
|
+
else
|
57
|
+
raise ArgumentError, "#{type.inspect} demographic does not support options" if options[:options]
|
58
|
+
end
|
59
|
+
raise ArgumentError, "#{type.inspect} demographic does not support :size option" if options[:size] unless %w(multiple_select_list select_list).include?(type.to_s)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Mosaic
|
4
|
+
module Lyris
|
5
|
+
class List < Object
|
6
|
+
attr_reader :cache_time,
|
7
|
+
:clickthru_url,
|
8
|
+
:footer_html,
|
9
|
+
:footer_text,
|
10
|
+
:handle_autoreply,
|
11
|
+
:handle_autoreply_email,
|
12
|
+
:handle_unsubscribe,
|
13
|
+
:handle_unsubscribe_email,
|
14
|
+
:id,
|
15
|
+
:last_sent,
|
16
|
+
:members,
|
17
|
+
:messages,
|
18
|
+
:name,
|
19
|
+
:reply_forward_email,
|
20
|
+
:reply_forward_subject,
|
21
|
+
:reply_from_email,
|
22
|
+
:reply_from_name,
|
23
|
+
:status
|
24
|
+
|
25
|
+
def active?
|
26
|
+
status == 'active'
|
27
|
+
end
|
28
|
+
|
29
|
+
def archived?
|
30
|
+
status == 'archived'
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def add(name, attributes = {})
|
35
|
+
reply = post('list', 'add') do |request|
|
36
|
+
put_data(request, 'name', name)
|
37
|
+
put_extra_data(request, 'CLICKTHRU_URL', attributes[:clickthru_url])
|
38
|
+
end
|
39
|
+
new attributes.merge(:id => reply.at('/DATASET/DATA').inner_html.to_i, :name => name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete(id)
|
43
|
+
reply = post('list', 'delete') do |request|
|
44
|
+
request.MLID id
|
45
|
+
end
|
46
|
+
new :id => id
|
47
|
+
end
|
48
|
+
|
49
|
+
def query(what)
|
50
|
+
reply = post('list', query_type(what))
|
51
|
+
reply.search('/DATASET/RECORD').collect do |record|
|
52
|
+
new :cache_time => get_xml_time_data(record, 'cache-time'),
|
53
|
+
:id => get_integer_data(record, 'name', :id),
|
54
|
+
:last_sent => get_date_data(record, 'last-sent'),
|
55
|
+
:members => get_integer_data(record, 'members'),
|
56
|
+
:messages => get_integer_data(record, 'messages'),
|
57
|
+
:name => get_data(record, 'name'),
|
58
|
+
:status => get_data(record, 'status')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
def query_type(what)
|
64
|
+
if what == :all
|
65
|
+
'query-listdata'
|
66
|
+
else
|
67
|
+
raise ArgumentError, "expected :all, got #{what.inspect}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Mosaic
|
2
|
+
module Lyris
|
3
|
+
class Message < Object
|
4
|
+
attr_reader :id,
|
5
|
+
:aol,
|
6
|
+
:category,
|
7
|
+
:charset,
|
8
|
+
:clickthru,
|
9
|
+
:clickthru_text,
|
10
|
+
:edited_at,
|
11
|
+
:format,
|
12
|
+
:from_email,
|
13
|
+
:from_name,
|
14
|
+
:html,
|
15
|
+
:htmlencoding,
|
16
|
+
:name,
|
17
|
+
:rule,
|
18
|
+
:segment,
|
19
|
+
:segment_id,
|
20
|
+
:sent,
|
21
|
+
:sent_at,
|
22
|
+
:stats_sent,
|
23
|
+
:subject,
|
24
|
+
:text,
|
25
|
+
:type
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def query(what, options = {})
|
29
|
+
if what == :all
|
30
|
+
query_all(options)
|
31
|
+
else
|
32
|
+
query_one(what, options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def query_all(options)
|
38
|
+
reply = post('message', 'query-listdata') do |request|
|
39
|
+
request.MLID options[:list_id] if options[:list_id]
|
40
|
+
end
|
41
|
+
reply.search('/DATASET/RECORD').collect do |record|
|
42
|
+
edit_time = get_time_data(record, 'last-edit-time')
|
43
|
+
edit_date = get_date_data(record, 'last-edit-date')
|
44
|
+
sent = get_data(record, 'sent')
|
45
|
+
sent_at = (sent == 'yes') ? get_date_data(record, 'date').to_time + get_time_offset_data(record, 'delivery') : nil
|
46
|
+
subject = get_data(record, 'subject')
|
47
|
+
new :id => get_integer_data(record, 'mid'),
|
48
|
+
:category => get_data(record, 'category'),
|
49
|
+
:edited_at => edit_date && (edit_date.to_time + edit_time.to_i - edit_time.to_date.to_time.to_i),
|
50
|
+
:format => get_data(record, 'message-format'),
|
51
|
+
:segment_id => get_integer_data(record, 'segment-id'),
|
52
|
+
:segment => get_data(record, 'segment'),
|
53
|
+
:sent => sent,
|
54
|
+
:sent_at => sent_at,
|
55
|
+
:stats_sent => get_integer_data(record, 'stats-sent'),
|
56
|
+
:subject => subject,
|
57
|
+
:type => get_data(record, 'mlid').blank? ? 'system' : (subject =~ /\APROOF: / ? 'test' : 'user')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def query_one(id, options)
|
62
|
+
reply = post('message', 'query-data') do |request|
|
63
|
+
request.MLID options[:list_id] if options[:list_id]
|
64
|
+
request.MID id
|
65
|
+
end
|
66
|
+
record = reply.at('/DATASET/RECORD')
|
67
|
+
sent = get_data(record, 'sent')
|
68
|
+
sent_at = (sent == 'yes') ? get_date_data(record, 'date').to_time + get_time_offset_data(record, 'delivery') : nil
|
69
|
+
new :id => id,
|
70
|
+
:aol => get_data(record, 'message-aol'),
|
71
|
+
:category => get_data(record, 'category'),
|
72
|
+
:charset => get_data(record, 'charset'),
|
73
|
+
:clickthru => get_boolean_data(record, 'clickthru', 'on'),
|
74
|
+
:clickthru_text => get_boolean_data(record, 'clickthru-text', 'on'),
|
75
|
+
:format => get_data(record, 'message-format'),
|
76
|
+
:from_email => get_data(record, 'from-email'),
|
77
|
+
:from_name => get_data(record, 'from-name'),
|
78
|
+
:html => get_data(record, 'message-html'),
|
79
|
+
:htmlencoding => get_data(record, 'htmlencoding'),
|
80
|
+
:segment_id => get_integer_data(record, 'rule'),
|
81
|
+
:segment => get_data(record, 'rule-name'),
|
82
|
+
:name => get_data(record, 'name'),
|
83
|
+
:sent => sent,
|
84
|
+
:sent_at => sent_at,
|
85
|
+
:subject => get_data(record, 'subject'),
|
86
|
+
:text => get_data(record, 'message-text')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def sent?
|
91
|
+
sent == 'yes'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'builder'
|
2
|
+
require 'net/https'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'uri'
|
5
|
+
require 'htmlentities'
|
6
|
+
|
7
|
+
require 'active_support/core_ext/object/blank'
|
8
|
+
require 'active_support/core_ext/time/calculations'
|
9
|
+
|
10
|
+
module Mosaic
|
11
|
+
module Lyris
|
12
|
+
class Error < RuntimeError; end
|
13
|
+
|
14
|
+
class Object
|
15
|
+
private_class_method :new
|
16
|
+
|
17
|
+
@@logger = nil
|
18
|
+
|
19
|
+
def initialize(attributes)
|
20
|
+
attributes.each do |attribute,value|
|
21
|
+
instance_variable_set "@#{attribute}", value unless value.nil?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_param
|
26
|
+
id && id.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def configuration
|
31
|
+
@@configuration ||= load_configuration
|
32
|
+
end
|
33
|
+
|
34
|
+
def configuration=(value)
|
35
|
+
@@configuration = value
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_configuration
|
39
|
+
configuration = YAML.load_file(File.join(::Rails.root.to_s,'config','lyris.yml')) rescue {}
|
40
|
+
configuration = configuration[::Rails.env] if configuration.include?(::Rails.env)
|
41
|
+
configuration
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
class << self
|
47
|
+
def callback_url
|
48
|
+
configuration['callback_url']
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_list_id
|
52
|
+
configuration['list_id']
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_trigger_id
|
56
|
+
configuration['trigger_id']
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_array_data(record, type)
|
60
|
+
if record.at("DATA[@type='#{type}']")
|
61
|
+
record.search("DATA[@type='#{type}']").collect do |data|
|
62
|
+
if block_given?
|
63
|
+
yield data
|
64
|
+
else
|
65
|
+
data.inner_html
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_boolean_data(record, type, value, attribute = nil, conditions = {})
|
72
|
+
if data = get_data(record, type, attribute, conditions)
|
73
|
+
data == value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_data(record, type, attribute = nil, conditions = {})
|
78
|
+
xpath = "DATA[@type='#{type}']"
|
79
|
+
xpath << conditions.collect { |a,v| "[@#{a}='#{v}']" }.join
|
80
|
+
if element = record.at(xpath)
|
81
|
+
data = attribute ? element[attribute] : element.inner_html
|
82
|
+
# TODO: fix encoding if necessary... seems like we should need to convert to UTF-8 here, but this works for now
|
83
|
+
HTMLEntities.new.decode(data.gsub(/&#(\d+);/) { Integer($1).chr })
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_date_data(record, type, attribute = nil, conditions = {})
|
88
|
+
data = get_data(record, type, attribute, conditions)
|
89
|
+
Date.parse(data) unless data.blank?
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_demographic_data(record)
|
93
|
+
if data = get_array_data(record, 'demographic') { |d| [ d[:id].to_i, d.inner_html ] }
|
94
|
+
data.inject({}) do |h,(k,v)|
|
95
|
+
case h[k]
|
96
|
+
when NilClass
|
97
|
+
h[k] = v
|
98
|
+
when Array
|
99
|
+
h[k] << v
|
100
|
+
else
|
101
|
+
h[k] = Array(h[k])
|
102
|
+
h[k] << v
|
103
|
+
end
|
104
|
+
h
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_element(record, element)
|
110
|
+
if data = record.at("/#{element}")
|
111
|
+
data.inner_html
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def get_integer_data(record, type, attribute = nil, conditions = {})
|
116
|
+
if data = get_data(record, type, attribute, conditions)
|
117
|
+
data.gsub(/,/,'').to_i
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_integer_element(record, element)
|
122
|
+
get_element(record, element).to_i
|
123
|
+
end
|
124
|
+
|
125
|
+
def get_time_data(record, type, attribute = nil, conditions = {})
|
126
|
+
if data = get_data(record, type, attribute, conditions)
|
127
|
+
Time.use_zone('Pacific Time (US & Canada)') do
|
128
|
+
Time.zone.parse(data)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def get_time_element(record, element)
|
134
|
+
if data = get_element(record, element)
|
135
|
+
Time.parse(data) + (Time.zone.utc_offset - Time.zone_offset('PST'))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_time_offset_data(record, type, attribute = nil, conditions = {})
|
140
|
+
if offset = get_integer_data(record, type, attribute, conditions)
|
141
|
+
offset + (Time.zone.utc_offset - Time.zone_offset('PST'))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def get_xml_time_data(record, type, attribute = nil, conditions = {})
|
146
|
+
if data = get_data(record, type, attribute, conditions)
|
147
|
+
Time.xmlschema(data)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def logger
|
152
|
+
@@logger ||= nil
|
153
|
+
end
|
154
|
+
|
155
|
+
def logger=(logger)
|
156
|
+
@@logger = logger
|
157
|
+
end
|
158
|
+
|
159
|
+
def password
|
160
|
+
configuration['password']
|
161
|
+
end
|
162
|
+
|
163
|
+
def post(type, activity, &block)
|
164
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
165
|
+
xml.instruct!
|
166
|
+
xml.DATASET do
|
167
|
+
xml.SITE_ID site_id
|
168
|
+
put_extra_data(xml, 'password', password)
|
169
|
+
block.call(xml) if block
|
170
|
+
end
|
171
|
+
input = xml.target!
|
172
|
+
|
173
|
+
request = Net::HTTP::Post.new("/API/mailing_list.html")
|
174
|
+
logger.debug ">>>>> REQUEST:\ntype=#{type}\nactivity=#{activity}\ninput=#{input}\n>>>>>" if logger
|
175
|
+
request.set_form_data('type' => type, 'activity' => activity, 'input' => input)
|
176
|
+
|
177
|
+
conn = Net::HTTP.new(server, 443)
|
178
|
+
conn.use_ssl = true
|
179
|
+
conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
180
|
+
|
181
|
+
conn.start do |http|
|
182
|
+
# TODO: parse encoding from declaration? update declaration after conversion?
|
183
|
+
reply = http.request(request).body
|
184
|
+
logger.debug ">>>>> REPLY:\n#{reply}\n>>>>>" if logger
|
185
|
+
document = Nokogiri.XML(reply)
|
186
|
+
raise Error, (document % '/DATASET/DATA').inner_html unless document % "/DATASET/TYPE[.='success']"
|
187
|
+
document
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def put_array_data(request, type, values)
|
192
|
+
Array(values).each do |value|
|
193
|
+
put_data(request, type, value)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def put_data(request, type, value, attributes = {})
|
198
|
+
request.DATA value, {:type => type}.merge(attributes) unless value.nil?
|
199
|
+
end
|
200
|
+
|
201
|
+
def put_demographic_data(request, demographics)
|
202
|
+
Array(demographics).each do |id, value|
|
203
|
+
Array(value).each do |v|
|
204
|
+
put_data(request, 'demographic', v, :id => id)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def put_extra_data(request, id, value)
|
210
|
+
put_data(request, 'extra', value, :id => id)
|
211
|
+
end
|
212
|
+
|
213
|
+
def server
|
214
|
+
configuration['server']
|
215
|
+
end
|
216
|
+
|
217
|
+
def site_id
|
218
|
+
configuration['site_id']
|
219
|
+
end
|
220
|
+
|
221
|
+
def triggers
|
222
|
+
configuration['triggers']
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|