eloqua 1.1.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.
- data/.gitignore +11 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +23 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +81 -0
- data/LICENSE +21 -0
- data/README.md +245 -0
- data/Rakefile +13 -0
- data/TODO.md +8 -0
- data/eloqua.gemspec +32 -0
- data/eloqua_initializer.tpl.rb +3 -0
- data/lib/eloqua.rb +51 -0
- data/lib/eloqua/api.rb +119 -0
- data/lib/eloqua/api/action.rb +41 -0
- data/lib/eloqua/api/service.rb +240 -0
- data/lib/eloqua/asset.rb +31 -0
- data/lib/eloqua/builder/templates.rb +31 -0
- data/lib/eloqua/builder/xml.rb +129 -0
- data/lib/eloqua/entity.rb +72 -0
- data/lib/eloqua/exceptions.rb +5 -0
- data/lib/eloqua/helper/attribute_map.rb +78 -0
- data/lib/eloqua/query.rb +291 -0
- data/lib/eloqua/remote_object.rb +274 -0
- data/lib/eloqua/version.rb +3 -0
- data/lib/eloqua/wsdl/action.wsdl +1 -0
- data/lib/eloqua/wsdl/data.wsdl +1 -0
- data/lib/eloqua/wsdl/email.wsdl +1 -0
- data/lib/eloqua/wsdl/service.wsdl +1 -0
- data/lib/tasks/test.rake +24 -0
- data/rspec.watchr +74 -0
- data/spec/fixtures/add_group_member/success.xml +18 -0
- data/spec/fixtures/create/contact_duplicate.xml +30 -0
- data/spec/fixtures/create/contact_success.xml +25 -0
- data/spec/fixtures/create_asset/failure.xml +30 -0
- data/spec/fixtures/create_asset/group_success.xml +25 -0
- data/spec/fixtures/delete_asset/access_deny.xml +31 -0
- data/spec/fixtures/describe_asset/success.xml +72 -0
- data/spec/fixtures/describe_asset_type/success.xml +23 -0
- data/spec/fixtures/describe_entity/success.xml +54 -0
- data/spec/fixtures/describe_entity_type/success.xml +45 -0
- data/spec/fixtures/get_member_count_in_step_by_status/success.xml +15 -0
- data/spec/fixtures/list_asset_types/success.xml +28 -0
- data/spec/fixtures/list_entity_types/success.xml +21 -0
- data/spec/fixtures/list_group_membership/success.xml +25 -0
- data/spec/fixtures/list_members_in_step_by_status/success.xml +15 -0
- data/spec/fixtures/query/contact_email_one.xml +38 -0
- data/spec/fixtures/query/contact_email_two.xml +56 -0
- data/spec/fixtures/query/contact_missing.xml +19 -0
- data/spec/fixtures/query/fault.xml +43 -0
- data/spec/fixtures/remove_group_member/success.xml +18 -0
- data/spec/fixtures/retrieve/contact_missing.xml +17 -0
- data/spec/fixtures/retrieve/contact_multiple.xml +3460 -0
- data/spec/fixtures/retrieve/contact_single.xml +38 -0
- data/spec/fixtures/retrieve_asset/failure.xml +17 -0
- data/spec/fixtures/retrieve_asset/success.xml +50 -0
- data/spec/fixtures/update/contact_success.xml +26 -0
- data/spec/lib/eloqua/api/action_spec.rb +36 -0
- data/spec/lib/eloqua/api/service_spec.rb +498 -0
- data/spec/lib/eloqua/api_spec.rb +133 -0
- data/spec/lib/eloqua/asset_spec.rb +63 -0
- data/spec/lib/eloqua/builder/templates_spec.rb +68 -0
- data/spec/lib/eloqua/builder/xml_spec.rb +254 -0
- data/spec/lib/eloqua/entity_spec.rb +224 -0
- data/spec/lib/eloqua/helper/attribute_map_spec.rb +14 -0
- data/spec/lib/eloqua/query_spec.rb +596 -0
- data/spec/lib/eloqua/remote_object_spec.rb +742 -0
- data/spec/lib/eloqua_spec.rb +171 -0
- data/spec/shared/attribute_map.rb +173 -0
- data/spec/shared/class_to_api_delegation.rb +50 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/support/helper.rb +73 -0
- metadata +366 -0
data/lib/eloqua/asset.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'eloqua/remote_object'
|
2
|
+
|
3
|
+
module Eloqua
|
4
|
+
|
5
|
+
class Asset < RemoteObject
|
6
|
+
|
7
|
+
self.remote_group = :asset
|
8
|
+
|
9
|
+
def add_member(entity)
|
10
|
+
member_operation(:add_group_member, entity)
|
11
|
+
end
|
12
|
+
|
13
|
+
def remove_member(entity)
|
14
|
+
member_operation(:remove_group_member, entity)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def member_operation(method, entity)
|
20
|
+
unless (entity.is_a?(Eloqua::Entity))
|
21
|
+
raise(ArgumentError, "Must pass a Eloqua::Entity")
|
22
|
+
end
|
23
|
+
unless (entity.persisted?)
|
24
|
+
raise(ArgumentError, "Cannot add member Entity has not been saved. (!entity.persisted?")
|
25
|
+
end
|
26
|
+
api.send(method, remote_type, id, entity.remote_type, entity.id)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Eloqua
|
2
|
+
module Builder
|
3
|
+
|
4
|
+
module Templates
|
5
|
+
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_attribute :builder_templates
|
10
|
+
self.builder_templates = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
|
15
|
+
def builder_template(name, *args)
|
16
|
+
template = builder_templates[name]
|
17
|
+
Proc.new do |xml|
|
18
|
+
template.call(xml, *args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_builder_template(name, &block)
|
23
|
+
builder_templates[name] = block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'eloqua/builder/templates'
|
2
|
+
|
3
|
+
module Eloqua
|
4
|
+
|
5
|
+
module Builder
|
6
|
+
|
7
|
+
# This could (and likely should) be submitted as a patch for
|
8
|
+
# the main builder class
|
9
|
+
class Xml < ::Builder::XmlMarkup
|
10
|
+
|
11
|
+
include Eloqua::Builder::Templates
|
12
|
+
|
13
|
+
# XML Templates
|
14
|
+
|
15
|
+
# For use with strings and integers may do strange
|
16
|
+
# things on the SOAP server side if given a float
|
17
|
+
define_builder_template :array do |xml, array|
|
18
|
+
array.each do |element|
|
19
|
+
tag = 'string'
|
20
|
+
if(element.is_a?(String))
|
21
|
+
tag = 'string'
|
22
|
+
elsif(element.is_a?(Numeric))
|
23
|
+
tag = 'int'
|
24
|
+
end
|
25
|
+
xml.arr(tag.to_sym, element)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
define_builder_template :int_array do |xml, array|
|
30
|
+
array.each do |element|
|
31
|
+
unless(element.is_a?(Numeric))
|
32
|
+
element = element.to_i
|
33
|
+
if(element == 0 || !element)
|
34
|
+
next
|
35
|
+
end
|
36
|
+
end
|
37
|
+
xml.arr(:int, element)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# For use with add/remove membership
|
42
|
+
define_builder_template :object do |xml, object_type, type, id|
|
43
|
+
xml.tag!(object_type) do
|
44
|
+
xml.object_type!(object_type) do
|
45
|
+
xml.template!(:object_type, type)
|
46
|
+
end
|
47
|
+
xml.Id(id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# For use with the entity function
|
52
|
+
define_builder_template :object_type do |xml, object|
|
53
|
+
xml.ID(object[:id])
|
54
|
+
xml.Name(object[:name])
|
55
|
+
xml.Type(object[:type])
|
56
|
+
end
|
57
|
+
|
58
|
+
# defines entity attribute fields for use in update/create
|
59
|
+
define_builder_template :fields do |xml, object_type, entity_attributes|
|
60
|
+
entity_attributes.each do |attribute, value|
|
61
|
+
xml.tag!("#{object_type.to_s.camelize}Fields") do
|
62
|
+
xml.InternalName(attribute.to_s)
|
63
|
+
xml.Value(value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Dynamic entity for update/create/etc...
|
69
|
+
|
70
|
+
define_builder_template :dynamic do |xml, object_type, type, id, attributes|
|
71
|
+
xml.tag!("#{object_type.to_s.camelize}Type") do
|
72
|
+
xml.template!(:object_type, type)
|
73
|
+
end
|
74
|
+
|
75
|
+
xml.FieldValueCollection do
|
76
|
+
xml.template!(:fields, object_type, attributes)
|
77
|
+
end
|
78
|
+
|
79
|
+
xml.Id(id) if id
|
80
|
+
end
|
81
|
+
|
82
|
+
delegate :builder_template, :to => self
|
83
|
+
|
84
|
+
|
85
|
+
def initialize(options = {}, &block)
|
86
|
+
super
|
87
|
+
@namespace = nil
|
88
|
+
@namespace = options[:namespace].to_sym if options[:namespace]
|
89
|
+
yield self if block_given?
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.create(options = {}, &block)
|
93
|
+
new(options, &block).target!
|
94
|
+
end
|
95
|
+
|
96
|
+
def template!(template, *args)
|
97
|
+
builder_template(template, *args).call(self)
|
98
|
+
end
|
99
|
+
|
100
|
+
def dynamic_object!(sym, *args, &block)
|
101
|
+
tag!("Dynamic#{sym.to_s.camelize}", *args, &block)
|
102
|
+
end
|
103
|
+
|
104
|
+
def object_type!(sym, *args, &block)
|
105
|
+
tag!("#{sym.to_s.camelize}Type", *args, &block)
|
106
|
+
end
|
107
|
+
|
108
|
+
def object_type_lower!(sym, *args, &block)
|
109
|
+
tag!("#{sym}Type", *args, &block)
|
110
|
+
end
|
111
|
+
|
112
|
+
def object_collection!(sym, *args, &block)
|
113
|
+
tag!("#{sym.to_s.pluralize.downcase}", *args, &block)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Extend to allow default namespace
|
117
|
+
def method_missing(sym, *args, &block)
|
118
|
+
if(@namespace && !args.first.kind_of?(Symbol))
|
119
|
+
args.unshift(sym.to_sym)
|
120
|
+
sym = @namespace
|
121
|
+
end
|
122
|
+
super(sym, *args, &block)
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'eloqua/remote_object'
|
2
|
+
|
3
|
+
module Eloqua
|
4
|
+
|
5
|
+
class Entity < RemoteObject
|
6
|
+
|
7
|
+
self.remote_group = :entity
|
8
|
+
|
9
|
+
# Returns an :id indexed list of memberships for contact
|
10
|
+
#
|
11
|
+
# # Example output
|
12
|
+
# {'1' => {:id => '1', :name => 'Contact Group Name', :type => 'ContactGroup}}
|
13
|
+
#
|
14
|
+
# @return [Hash] Integer => Hash
|
15
|
+
def list_memberships
|
16
|
+
self.class.list_memberships(id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_membership(asset)
|
20
|
+
asset.add_member(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove_membership(asset)
|
24
|
+
asset.remove_member(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
|
29
|
+
# Returns an :id indexed list of memberships for given contact id
|
30
|
+
#
|
31
|
+
# # Example output
|
32
|
+
# {'1' => {:id => '1', :name => 'Contact Group Name', :type => 'ContactGroup}}
|
33
|
+
#
|
34
|
+
# @param [String, Integer] contact id
|
35
|
+
# @return [Hash] Integer => Hash
|
36
|
+
def list_memberships(id)
|
37
|
+
memberships = api.list_memberships(remote_type, id)
|
38
|
+
|
39
|
+
if(memberships && !memberships.empty?)
|
40
|
+
memberships.inject({}) do |map, membership|
|
41
|
+
map[membership[:id]] = membership
|
42
|
+
map
|
43
|
+
end
|
44
|
+
else
|
45
|
+
memberships || {}
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def where(conditions = nil, fields = [], limit = 200, page = 1)
|
51
|
+
if(conditions)
|
52
|
+
query = where
|
53
|
+
conditions.each do |key, value|
|
54
|
+
query.on(key, '=', value)
|
55
|
+
end
|
56
|
+
query.fields(fields) if fields
|
57
|
+
query.limit(limit)
|
58
|
+
query.page(page)
|
59
|
+
results = query.all
|
60
|
+
if(results.blank?)
|
61
|
+
false
|
62
|
+
else
|
63
|
+
results
|
64
|
+
end
|
65
|
+
else
|
66
|
+
Eloqua::Query.new(self)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Eloqua
|
2
|
+
module Helper
|
3
|
+
|
4
|
+
module AttributeMap
|
5
|
+
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_attribute :attribute_map, :attribute_map_reverse
|
10
|
+
|
11
|
+
attr_reader :instance_reverse_keys
|
12
|
+
|
13
|
+
self.attribute_map = {}.with_indifferent_access
|
14
|
+
self.attribute_map_reverse = {}.with_indifferent_access
|
15
|
+
|
16
|
+
class << self
|
17
|
+
alias_method_chain :inherited, :clone_attributes
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
|
24
|
+
def inherited_with_clone_attributes(klass)
|
25
|
+
klass.attribute_map = attribute_map.clone
|
26
|
+
klass.attribute_map_reverse = attribute_map_reverse.clone
|
27
|
+
inherited_without_clone_attributes(klass) if method_defined?(:inherited_without_clone_attributes)
|
28
|
+
end
|
29
|
+
|
30
|
+
def eloqua_attribute(attribute)
|
31
|
+
(attribute_map_reverse.fetch(attribute) { attribute }).to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
def map_attribute(attribute)
|
35
|
+
attribute_map.fetch(attribute) { attribute.to_s }
|
36
|
+
end
|
37
|
+
|
38
|
+
# This shoud always be used over directly editing attribute_map
|
39
|
+
def map(hash)
|
40
|
+
hash.each do |key, value|
|
41
|
+
value = value.to_sym
|
42
|
+
key = key.to_sym
|
43
|
+
|
44
|
+
attribute_map[key] = value
|
45
|
+
attribute_map_reverse[value] = key
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
module InstanceMethods
|
52
|
+
|
53
|
+
def map_attributes(attributes)
|
54
|
+
@instance_reverse_keys ||= attribute_map_reverse.clone
|
55
|
+
results = {}.with_indifferent_access
|
56
|
+
|
57
|
+
attributes.each do |key, value|
|
58
|
+
formatted_key = attribute_map.fetch(key) { key.to_s.gsub(/^C_/, '').underscore }
|
59
|
+
@instance_reverse_keys[formatted_key] = key
|
60
|
+
results[formatted_key] = value
|
61
|
+
end
|
62
|
+
results
|
63
|
+
end
|
64
|
+
|
65
|
+
def reverse_map_attributes(attributes)
|
66
|
+
results = {}.with_indifferent_access
|
67
|
+
attributes.each do |key, value|
|
68
|
+
results[@instance_reverse_keys.fetch(key){key}] = value
|
69
|
+
end
|
70
|
+
results
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
data/lib/eloqua/query.rb
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'eloqua/api/service'
|
2
|
+
require 'eloqua/remote_object'
|
3
|
+
|
4
|
+
module Eloqua
|
5
|
+
class Query
|
6
|
+
|
7
|
+
delegate :api, :to => :remote_object
|
8
|
+
|
9
|
+
attr_reader :collection, :remote_object, :conditions, :total_pages
|
10
|
+
attr_internal :current_page, :query_started
|
11
|
+
|
12
|
+
|
13
|
+
# The amount of time in seconds to wait before sending another request to Eloqua
|
14
|
+
@@request_delay = 1
|
15
|
+
cattr_accessor :request_delay
|
16
|
+
|
17
|
+
# Create a new query to attach conditions to.
|
18
|
+
#
|
19
|
+
# class Contact < Eloqua::Entity
|
20
|
+
# remote_type = api.remote_type('Contact')
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Eloqua::Query.new(Contact)
|
24
|
+
#
|
25
|
+
# @param [Eloqua::RemoteObject] or one of its descendants
|
26
|
+
def initialize(remote_object)
|
27
|
+
unless(remote_object.is_a?(Class) && Eloqua::RemoteObject >= remote_object)
|
28
|
+
raise(ArgumentError, 'must provide an Eloqua::RemoteObject or one of its descendants')
|
29
|
+
end
|
30
|
+
|
31
|
+
@page = 1
|
32
|
+
@limit = 200
|
33
|
+
@collection = []
|
34
|
+
@remote_object = remote_object
|
35
|
+
@conditions = []
|
36
|
+
@fields = nil
|
37
|
+
@has_requested = false
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
## CHAIN-ABLES they reset the has_requested? but do not clear the collection
|
42
|
+
|
43
|
+
# Sets or gets limit
|
44
|
+
#
|
45
|
+
# query.limit(5) # sets limit returns self
|
46
|
+
# query.limit # returns 5
|
47
|
+
#
|
48
|
+
# @param [Integer]
|
49
|
+
# @return [self, Integer]
|
50
|
+
def limit(value = nil); end
|
51
|
+
|
52
|
+
# Sets or gets page
|
53
|
+
#
|
54
|
+
# query.page(5) # sets limit returns self
|
55
|
+
# query.page # returns 5
|
56
|
+
#
|
57
|
+
# @param [Integer]
|
58
|
+
# @return [self, Integer]
|
59
|
+
#
|
60
|
+
def page(value = nil); end
|
61
|
+
|
62
|
+
# Sets or gets the array of fields to find.
|
63
|
+
# Can use a literal string or a symbol of a {Eloqua::RemoteObject#map mapped} attribute
|
64
|
+
#
|
65
|
+
# query.fields([:email, 'Date'])
|
66
|
+
# query.fields # returns [:email, 'Date']
|
67
|
+
#
|
68
|
+
# @see Eloqua::RemoteObject::map
|
69
|
+
# @param [Array]
|
70
|
+
# @return [self, Array]
|
71
|
+
def fields(value = nil); end
|
72
|
+
|
73
|
+
|
74
|
+
# This mess defines the limit and page getter/setter methods
|
75
|
+
# when they are set they will also set #has_requested? to false
|
76
|
+
[:fields, :limit, :page].each do |attr|
|
77
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
78
|
+
remove_method(:#{attr})
|
79
|
+
def #{attr}(value = nil)
|
80
|
+
if(value.nil?)
|
81
|
+
@#{attr}
|
82
|
+
else
|
83
|
+
@has_requested = false
|
84
|
+
@#{attr} = value
|
85
|
+
self
|
86
|
+
end
|
87
|
+
end
|
88
|
+
RUBY
|
89
|
+
end
|
90
|
+
|
91
|
+
# Clears all conditions added by {on}
|
92
|
+
#
|
93
|
+
# query.on(:id, '>', '1')
|
94
|
+
# query.clear_conditions!
|
95
|
+
#
|
96
|
+
def clear_conditions!
|
97
|
+
@has_requested = false
|
98
|
+
conditions.clear
|
99
|
+
end
|
100
|
+
|
101
|
+
# Adds a condition to the query; may be chained.
|
102
|
+
#
|
103
|
+
# query.on(:email, '=', 'value').on('created_at', '>', '2011-04-20')
|
104
|
+
#
|
105
|
+
# @param [String, Symbol] field name
|
106
|
+
# @param [String] operator can use: `[ =, !=, <, >, >=, <=]`
|
107
|
+
# @param [String] value to search for
|
108
|
+
# @return self
|
109
|
+
def on(field, operator, value)
|
110
|
+
@has_requested = false
|
111
|
+
@conditions << {
|
112
|
+
:field => field,
|
113
|
+
:type => operator,
|
114
|
+
:value => value
|
115
|
+
}
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
# Send the built request to eloqua
|
121
|
+
#
|
122
|
+
# query.on(:email, '=', '*') # wildcard
|
123
|
+
# query.request!
|
124
|
+
# query.collection # Array of results
|
125
|
+
# query.current_page # Current page
|
126
|
+
# query.total_pages # Number of pages
|
127
|
+
#
|
128
|
+
# @return self
|
129
|
+
def request!
|
130
|
+
return if has_requested?
|
131
|
+
sleep_for = wait_for_request_delay
|
132
|
+
if(sleep_for)
|
133
|
+
sleep(sleep_for)
|
134
|
+
end
|
135
|
+
xml_query = api.builder do |xml|
|
136
|
+
xml.eloquaType do
|
137
|
+
xml.template!(:object_type, remote_object.remote_type)
|
138
|
+
end
|
139
|
+
xml.searchQuery(build_query)
|
140
|
+
|
141
|
+
# This won't harm anything but it is changing the
|
142
|
+
# fields to its mapped elouqa name.
|
143
|
+
if(!fields.blank? && fields.is_a?(Array))
|
144
|
+
fields.map! do |field|
|
145
|
+
field = remote_object.eloqua_attribute(field)
|
146
|
+
end
|
147
|
+
xml.fieldNames do
|
148
|
+
xml.template!(:array, fields)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
xml.pageNumber(page)
|
153
|
+
xml.pageSize(limit)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Add timestamp of when we made request
|
157
|
+
@_query_started = Time.now
|
158
|
+
result = api.request(:query, xml_query)
|
159
|
+
|
160
|
+
# Clear collection
|
161
|
+
collection.clear
|
162
|
+
|
163
|
+
# Mark as requested
|
164
|
+
@has_requested = true
|
165
|
+
|
166
|
+
|
167
|
+
if(result[:entities])
|
168
|
+
@total_pages = result[:total_pages].to_i
|
169
|
+
entities = Eloqua.format_results_for_array(result, :entities, :dynamic_entity)
|
170
|
+
records = entities.inject([]) do |records, entity|
|
171
|
+
record_attrs = {}
|
172
|
+
entity_id = entity[:id]
|
173
|
+
entity[:field_value_collection][:entity_fields].each do |entity_attr|
|
174
|
+
record_attrs[entity_attr[:internal_name]] = entity_attr[:value]
|
175
|
+
end
|
176
|
+
record_attrs[remote_object.primary_key] = entity_id
|
177
|
+
record_object = remote_object.new(record_attrs, :remote)
|
178
|
+
|
179
|
+
collection << record_object
|
180
|
+
end
|
181
|
+
collection
|
182
|
+
else
|
183
|
+
@total_pages = 0
|
184
|
+
false
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def wait_for_request_delay
|
189
|
+
if(request_delay && query_started)
|
190
|
+
now = Time.now
|
191
|
+
wait_until = Time.at((request_delay + query_started.to_f))
|
192
|
+
if(wait_until > now)
|
193
|
+
wait_until - now
|
194
|
+
end
|
195
|
+
else
|
196
|
+
false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
# Has the request been made yet?
|
202
|
+
#
|
203
|
+
# query.has_requested? # false
|
204
|
+
# query.on(:email, '=', '*').request!
|
205
|
+
# query.has_requested? # true
|
206
|
+
#
|
207
|
+
# @return [Boolean]
|
208
|
+
def has_requested?
|
209
|
+
@has_requested
|
210
|
+
end
|
211
|
+
|
212
|
+
# Sends request if not already set and iterates through result
|
213
|
+
#
|
214
|
+
# query.each do |record|
|
215
|
+
# record.class # query.remote_object
|
216
|
+
# end
|
217
|
+
#
|
218
|
+
# Currently this is a shortcut for
|
219
|
+
#
|
220
|
+
# query.all.each do |record|
|
221
|
+
# ...
|
222
|
+
# end
|
223
|
+
#
|
224
|
+
# @param [Proc] a block iterator
|
225
|
+
def each(&block)
|
226
|
+
all.each(&block)
|
227
|
+
end
|
228
|
+
|
229
|
+
# Sends request and returns collection
|
230
|
+
#
|
231
|
+
# query.on(:email, '=', '*').all # => [Eloqua::RemoteObject.new(), ...]
|
232
|
+
#
|
233
|
+
# @return [Array] collection of Eloqua::RemoteObject
|
234
|
+
def all
|
235
|
+
request!
|
236
|
+
collection
|
237
|
+
end
|
238
|
+
|
239
|
+
# Iterates through each page up to max_pages
|
240
|
+
# when max_pages is nil (default) will iterate through
|
241
|
+
# each page yielding a block with a record.
|
242
|
+
#
|
243
|
+
# with max_pages you could and then resume the loop through
|
244
|
+
# pages
|
245
|
+
#
|
246
|
+
# query.each_page(2) |record|
|
247
|
+
# query.total_pages # 10
|
248
|
+
# query.page # 1 ... 2
|
249
|
+
# end
|
250
|
+
#
|
251
|
+
# ...
|
252
|
+
#
|
253
|
+
# query.each_page(2) |record|
|
254
|
+
# query.total_pages # 10
|
255
|
+
# query.page # 3 ... 4
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
# @see Query#each
|
259
|
+
# @param [Integer] max pages to iterate through
|
260
|
+
def each_page(max_pages = nil, &block)
|
261
|
+
each(&block)
|
262
|
+
while(total_pages > page)
|
263
|
+
break if max_pages && page >= max_pages
|
264
|
+
page(page + 1)
|
265
|
+
each(&block)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
protected
|
270
|
+
|
271
|
+
# Builds query from conditions
|
272
|
+
# conditions are assembled by their field, type and then value as below
|
273
|
+
#
|
274
|
+
# #{field}#{type}'#{value}'
|
275
|
+
#
|
276
|
+
# then joined by AND which acts more like an SQL "OR" in Eloqua
|
277
|
+
# > and < are escaped with > and <
|
278
|
+
def build_query
|
279
|
+
conditions.inject([]) do |parts, cond|
|
280
|
+
part = ""
|
281
|
+
part << remote_object.eloqua_attribute(cond[:field])
|
282
|
+
part << cond[:type].to_s
|
283
|
+
part << "'#{cond[:value]}'"
|
284
|
+
parts << part
|
285
|
+
end.join(" AND ")
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|