Skip to content

Commit

Permalink
Eloqua API. For eventual use as gem. Currently supports Entity [Query…
Browse files Browse the repository at this point in the history
…, Update, Retrieve] via an ActiveRecord like api. Early alpha version currently. abstracted out from main app
  • Loading branch information
lightsofapollo committed Apr 8, 2011
1 parent 158f917 commit 6760f45
Show file tree
Hide file tree
Showing 29 changed files with 5,547 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eloqua_initializer.rb
.DS_Store
12 changes: 12 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
source :rubygems

gem 'savon'
gem 'builder'
gem 'activemodel'
gem 'activesupport'

gem 'savon_spec', :groups => [:test, :development]
gem 'rspec', "> 2.0", :groups => [:test, :development]
gem 'flexmock', :group => :test
gem 'watchr', :groups => [:test, :development]
gem 'ruby-fsevent', :groups => [:test, :development]
54 changes: 54 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
GEM
remote: http://rubygems.org/
specs:
activemodel (3.0.6)
activesupport (= 3.0.6)
builder (~> 2.1.2)
i18n (~> 0.5.0)
activesupport (3.0.6)
builder (2.1.2)
crack (0.1.8)
diff-lcs (1.1.2)
flexmock (0.9.0)
gyoku (0.4.2)
builder (>= 2.1.2)
httpi (0.9.2)
ntlm-http (>= 0.1.1)
rack
i18n (0.5.0)
mocha (0.9.12)
ntlm-http (0.1.1)
rack (1.2.2)
rspec (2.5.0)
rspec-core (~> 2.5.0)
rspec-expectations (~> 2.5.0)
rspec-mocks (~> 2.5.0)
rspec-core (2.5.1)
rspec-expectations (2.5.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.5.0)
ruby-fsevent (0.2.1)
savon (0.8.6)
builder (>= 2.1.2)
crack (~> 0.1.8)
gyoku (>= 0.3.0)
httpi (>= 0.7.8)
savon_spec (0.1.4)
mocha (>= 0.9.8)
rspec (>= 2.0.0)
savon (~> 0.8.0)
watchr (0.7)

PLATFORMS
ruby

DEPENDENCIES
activemodel
activesupport
builder
flexmock
rspec (> 2.0)
ruby-fsevent
savon
savon_spec
watchr
3 changes: 3 additions & 0 deletions eloqua_initializer.tpl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Eloqua.configure do |config|
config.authenticate('Company\\User', 'Password')
end
Binary file added lib/.DS_Store
Binary file not shown.
20 changes: 20 additions & 0 deletions lib/eloqua.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'eloqua/api'
require 'eloqua/entity'

module Eloqua

autoload :API, 'eloqua/api'
autoload :Entity, 'eloqua/entity'

mattr_accessor :user, :password

def self.configure(&block)
yield self
end

def self.authenticate(user, password)
self.user = user
self.password = password
end

end
147 changes: 147 additions & 0 deletions lib/eloqua/api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
require 'savon'

require 'active_support/core_ext/class'
require 'active_support/concern'

require 'eloqua/builder/xml'
require 'eloqua/builder/templates'

module Eloqua

class API

# The namespace for Eloqua Array objects
XML_NS_ARRAY = 'http://schemas.microsoft.com/2003/10/Serialization/Arrays'

# WSDLs are from 3-30-2011
WSDL = {
:service => File.dirname(__FILE__) + '/wsdl/service.wsdl',
:data => File.dirname(__FILE__) + '/wsdl/data.wsdl',
:email => File.dirname(__FILE__) + '/wsdl/email.wsdl'
}

include Eloqua::Builder::Templates

# XML Templates

# For use with strings and integers may do strange
# things on the SOAP server side if given a float
define_builder_template :array do |xml, array|
array.each do |element|
tag = 'string'
if(element.is_a?(String))
tag = 'string'
elsif(element.is_a?(Numeric))
tag = 'int'
end
xml.arr(tag.to_sym, element)
end
end

define_builder_template :int_array do |xml, array|
array.each do |element|
unless(element.is_a?(Numeric))
element = element.to_i
if(element == 0 || !element)
next
end
end
xml.arr(:int, element)
end
end

# For use with the entity function
define_builder_template :entity do |xml, entity|
xml.ID(entity['ID'])
xml.Name(entity['Name'])
xml.Type(entity['Type'])
end

# defines entity attribute fields for use in update/create
define_builder_template :entity_fields do |xml, entity_attributes|
entity_attributes.each do |attribute, value|
xml.EntityFields do
xml.InternalName(attribute.to_s)
xml.Value(value)
end
end
end

# Dynamic entity for update/create/etc...

define_builder_template :dynamic_entity do |xml, type, id, attributes|
xml.EntityType(&builder_template(:entity, type))
xml.FieldValueCollection(&builder_template(:entity_fields, attributes))
xml.Id(id)
end


class << self

@@clients = {}

def reset_clients
@@clients = {}
end

def clients
@@clients
end

# There are three wsdl types for eloqua
# 1. Service
# 2. Data
# 3. Email
def client(type)
if(!Eloqua.user || !Eloqua.password)
raise('Eloqua.user or Eloqua.password is not set see Eloqua.authenticate')
end
clients[type] ||= Savon::Client.new do
wsdl.document = WSDL[type]
wsse.credentials Eloqua.user, Eloqua.password
end
end

def builder(&block)
Eloqua::Builder::Xml.new(:namespace => :wsdl, &block)
end

def entity(name, type = 'Base', id = 0)
{
'Name' => name,
'Type' => type,
'ID' => id
}
end

def request(type, name, soap_body = nil, &block)
result = send_remote_request(type, name, soap_body, &block)
if(result)
result = result.to_hash
response_key = "#{name}_response".to_sym
result_key = "#{name}_result".to_sym
if(result.has_key?(response_key))
result = result[response_key]
end
if(result.has_key?(result_key))
result = result[result_key]
end
end
result
end


# Sends remote request and returns a response object
def send_remote_request(type, name, soap_body = nil, &block)
client(type).request(:wsdl, name) do
soap.namespaces["xmlns:arr"] = XML_NS_ARRAY
soap.element_form_default = :qualified
soap.body = soap_body if soap_body
instance_eval(&block) if block_given?
end
end

end
end

end
31 changes: 31 additions & 0 deletions lib/eloqua/builder/templates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Eloqua
module Builder

module Templates

extend ActiveSupport::Concern

included do
class_attribute :builder_templates
self.builder_templates = {}
end

module ClassMethods

def builder_template(name, *args)
template = builder_templates[name]
Proc.new do |xml|
template.call(xml, *args)
end
end

def define_builder_template(name, &block)
builder_templates[name] = block
end
end

end


end
end
29 changes: 29 additions & 0 deletions lib/eloqua/builder/xml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Eloqua

module Builder

# This could (and likely should) be submitted as a patch for
# the main builder class
class Xml < ::Builder::XmlMarkup

def initialize(options = {})
super
@namespace = nil
@namespace = options[:namespace].to_sym if options[:namespace]
end


# Extend to allow default namespace
def method_missing(sym, *args, &block)
if(@namespace && !args.first.kind_of?(Symbol))
args.unshift(sym.to_sym)
sym = @namespace
end
super(sym, *args, &block)
end

end

end

end
Loading

0 comments on commit 6760f45

Please sign in to comment.