autotask_ruby 0.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.
- checksums.yaml +7 -0
- data/.gitignore +54 -0
- data/.rspec +3 -0
- data/.rubocop.yml +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +152 -0
- data/Guardfile +72 -0
- data/LICENSE +21 -0
- data/README.md +73 -0
- data/Rakefile +8 -0
- data/atws-1_6.wsdl +3263 -0
- data/atws.wsdl +3191 -0
- data/autotask_ruby.gemspec +51 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/autotask_ruby.rb +30 -0
- data/lib/autotask_ruby/account.rb +14 -0
- data/lib/autotask_ruby/account_to_do.rb +20 -0
- data/lib/autotask_ruby/action_type.rb +13 -0
- data/lib/autotask_ruby/appointment.rb +20 -0
- data/lib/autotask_ruby/association.rb +38 -0
- data/lib/autotask_ruby/client.rb +91 -0
- data/lib/autotask_ruby/configuration.rb +25 -0
- data/lib/autotask_ruby/constants.rb +7 -0
- data/lib/autotask_ruby/contact.rb +26 -0
- data/lib/autotask_ruby/create_response.rb +5 -0
- data/lib/autotask_ruby/delete_response.rb +5 -0
- data/lib/autotask_ruby/entity.rb +113 -0
- data/lib/autotask_ruby/fields.rb +16 -0
- data/lib/autotask_ruby/project.rb +20 -0
- data/lib/autotask_ruby/query.rb +22 -0
- data/lib/autotask_ruby/query_response.rb +8 -0
- data/lib/autotask_ruby/resource.rb +22 -0
- data/lib/autotask_ruby/response.rb +28 -0
- data/lib/autotask_ruby/service_call.rb +24 -0
- data/lib/autotask_ruby/service_call_ticket.rb +11 -0
- data/lib/autotask_ruby/service_call_ticket_resource.rb +11 -0
- data/lib/autotask_ruby/task.rb +19 -0
- data/lib/autotask_ruby/ticket.rb +18 -0
- data/lib/autotask_ruby/version.rb +5 -0
- data/lib/autotask_ruby/zone_info.rb +31 -0
- metadata +273 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'autotask_ruby/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'autotask_ruby'
|
9
|
+
spec.version = AutotaskRuby::VERSION
|
10
|
+
spec.authors = ['Jared L Jennings']
|
11
|
+
spec.email = ['jared@jaredjennings.org']
|
12
|
+
|
13
|
+
spec.summary = 'A ruby client for the Autotask API'
|
14
|
+
spec.description = 'A ruby client for the Autotask API. The client tries to use a full-featured approach.'
|
15
|
+
spec.homepage = 'https://github.com/trepidity/autotask_ruby'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
19
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
20
|
+
if spec.respond_to?(:metadata)
|
21
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
22
|
+
spec.metadata['source_code_uri'] = 'https://github.com/trepidity/autotask_ruby'
|
23
|
+
else
|
24
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
25
|
+
end
|
26
|
+
|
27
|
+
# Specify which files should be added to the gem when it is released.
|
28
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
29
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
30
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
31
|
+
end
|
32
|
+
spec.bindir = 'exe'
|
33
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
34
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
35
|
+
spec.require_paths = ['lib']
|
36
|
+
|
37
|
+
spec.add_runtime_dependency 'activesupport', '~> 5.2'
|
38
|
+
spec.add_runtime_dependency 'savon', '~> 2.12'
|
39
|
+
|
40
|
+
spec.add_development_dependency 'awesome_print', '~> 1.8'
|
41
|
+
spec.add_development_dependency 'bundler', '~> 1.17'
|
42
|
+
spec.add_development_dependency 'byebug', '~> 10.0'
|
43
|
+
spec.add_development_dependency 'dotenv', '~> 2.5'
|
44
|
+
spec.add_development_dependency 'guard', '~> 2.15'
|
45
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.7'
|
46
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.31'
|
47
|
+
spec.add_development_dependency 'rake', '~> 12.3'
|
48
|
+
spec.add_development_dependency 'rspec', '~> 3.8'
|
49
|
+
spec.add_development_dependency 'rubocop', '~> 0.62'
|
50
|
+
spec.add_development_dependency 'webmock', '~> 3.5'
|
51
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'autotask_ruby'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
require 'active_support/core_ext/class/attribute'
|
5
|
+
require 'active_support/core_ext/string/inflections'
|
6
|
+
require 'active_support/core_ext/hash'
|
7
|
+
require 'savon'
|
8
|
+
require 'nokogiri'
|
9
|
+
require 'autotask_ruby/configuration'
|
10
|
+
require 'autotask_ruby/constants'
|
11
|
+
require 'autotask_ruby/query'
|
12
|
+
require 'autotask_ruby/association'
|
13
|
+
require 'autotask_ruby/response'
|
14
|
+
require 'autotask_ruby/query_response'
|
15
|
+
require 'autotask_ruby/create_response'
|
16
|
+
require 'autotask_ruby/delete_response'
|
17
|
+
require 'autotask_ruby/zone_info'
|
18
|
+
require 'autotask_ruby/entity'
|
19
|
+
require 'autotask_ruby/client'
|
20
|
+
require 'autotask_ruby/resource'
|
21
|
+
require 'autotask_ruby/account'
|
22
|
+
require 'autotask_ruby/contact'
|
23
|
+
require 'autotask_ruby/account_to_do'
|
24
|
+
require 'autotask_ruby/appointment'
|
25
|
+
require 'autotask_ruby/task'
|
26
|
+
require 'autotask_ruby/ticket'
|
27
|
+
require 'autotask_ruby/project'
|
28
|
+
require 'autotask_ruby/service_call'
|
29
|
+
require 'autotask_ruby/service_call_ticket'
|
30
|
+
require 'autotask_ruby/service_call_ticket_resource'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AutotaskRuby
|
4
|
+
# Represents the Autotask Account Entity
|
5
|
+
class Account
|
6
|
+
include Entity
|
7
|
+
|
8
|
+
FIELDS = %i[id Address1 City Country CreateDate AccountName AccountNumber Phone PostalCode State Active].freeze
|
9
|
+
.each do |field|
|
10
|
+
self.attr_accessor :"#{field.to_s.underscore}"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AutotaskRuby
|
4
|
+
# Represents the Autotask AccountToDo entity
|
5
|
+
class AccountToDo
|
6
|
+
include AutotaskRuby::Entity
|
7
|
+
include AutotaskRuby::Query
|
8
|
+
|
9
|
+
FIELDS = %i[id AccountID ContactID ActivityDescription StartDateTime EndDateTime
|
10
|
+
AssignedToResourceID ActionType CreateDateTime LastModifiedDate].freeze
|
11
|
+
.each do |field|
|
12
|
+
self.attr_accessor :"#{field.to_s.underscore}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def post_initialize
|
16
|
+
belongs_to :resource
|
17
|
+
belongs_to :account
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AutotaskRuby
|
4
|
+
# Represents the Autotask Entity Action Type
|
5
|
+
class ActionType
|
6
|
+
include Entity
|
7
|
+
|
8
|
+
FIELDS = %i[id Name View Active SystemActionType].freeze
|
9
|
+
.each do |field|
|
10
|
+
self.attr_accessor :"#{field.to_s.underscore}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AutotaskRuby
|
4
|
+
|
5
|
+
# Represents an AutoTask Appointment Entity
|
6
|
+
class Appointment
|
7
|
+
include Entity
|
8
|
+
|
9
|
+
FIELDS = %i[id Title Description ResourceID StartDateTime EndDateTime CreateDateTime UpdateDateTime].freeze
|
10
|
+
.each do |field|
|
11
|
+
self.attr_accessor :"#{field.to_s.underscore}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_initialize
|
15
|
+
belongs_to :resource
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module AutotaskRuby
|
2
|
+
# handles loading associated entities.
|
3
|
+
module Association
|
4
|
+
# loads parent entity.
|
5
|
+
# Thanks to scoop for this example.
|
6
|
+
def belongs_to(name, options = {})
|
7
|
+
name = name.to_s
|
8
|
+
klass = "#{(options[:class_name] || name).to_s.classify}"
|
9
|
+
foreign_key = name.foreign_key
|
10
|
+
define_singleton_method(name) do
|
11
|
+
find(klass, send(foreign_key))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Example, an appointment can have one contact.
|
16
|
+
# Thanks to scoop for this example.
|
17
|
+
def has_one(name, options = {})
|
18
|
+
name = name.to_s
|
19
|
+
options.reverse_merge! foreign_key: self.to_s.foreign_key.camelize
|
20
|
+
klass = "#{(options[:class_name] || name).to_s.classify}"
|
21
|
+
define_singleton_method(name) do
|
22
|
+
find(klass, options[:foreign_key], id).first
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# loads child entities.
|
27
|
+
# Example: A project can have many tasks.
|
28
|
+
# Thanks to scoop for this example.
|
29
|
+
def has_many(name, options = {})
|
30
|
+
name = name.to_s
|
31
|
+
options.reverse_merge! foreign_key: self.to_s.foreign_key.camelize
|
32
|
+
klass = "#{(options[:class_name] || name).to_s.classify}"
|
33
|
+
define_singleton_method(name) do
|
34
|
+
query(klass, options[:foreign_key], id)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'autotask_ruby/version'
|
4
|
+
require 'autotask_ruby/resource'
|
5
|
+
|
6
|
+
module AutotaskRuby
|
7
|
+
|
8
|
+
# the primary client that interfaces with the SOAP Client that will interface with AutoTask.
|
9
|
+
class Client
|
10
|
+
attr_accessor :soap_client, :headers, :logger
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@version = options[:version] || AutotaskRuby.configuration.version
|
14
|
+
integration_code = options[:integration_code] || AutotaskRuby.configuration.integration_code
|
15
|
+
@headers = {
|
16
|
+
'tns:AutotaskIntegrations' =>
|
17
|
+
{
|
18
|
+
'tns:IntegrationCode' => integration_code
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
@ssl_version = options[:ssl_version] || :TLSv1_2
|
23
|
+
|
24
|
+
@host = options[:host] || 'webservices.autotask.net'
|
25
|
+
@endpoint = options[:endpoint] || "https://#{@host}/ATServices/#{@version}/atws.asmx"
|
26
|
+
|
27
|
+
# Override optional Savon attributes
|
28
|
+
savon_options = {}
|
29
|
+
%w[read_timeout open_timeout proxy raise_errors log_level basic_auth log raise_errors].each do |prop|
|
30
|
+
key = prop.to_sym
|
31
|
+
savon_options[key] = options[key] if options.key?(key)
|
32
|
+
end
|
33
|
+
|
34
|
+
@soap_client = Savon.client({
|
35
|
+
wsdl: './atws.wsdl',
|
36
|
+
soap_header: @headers,
|
37
|
+
namespaces: { xmlns: AutotaskRuby.configuration.namespace },
|
38
|
+
logger: Logger.new($stdout),
|
39
|
+
raise_errors: false,
|
40
|
+
log: true,
|
41
|
+
endpoint: @endpoint,
|
42
|
+
ssl_version: @ssl_version # Sets ssl_version for HTTPI adapter
|
43
|
+
}.update(savon_options))
|
44
|
+
end
|
45
|
+
|
46
|
+
# Public: Get the names of all wsdl operations.
|
47
|
+
# List all available operations from the atws.wsdl
|
48
|
+
def operations
|
49
|
+
@soap_client.operations
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param entity, id
|
53
|
+
# pass in the entity_type, I.E. AccountToDo, Resource, etc. and the ID of the entity.
|
54
|
+
# @return Entity
|
55
|
+
# Returns a single Entity if a match was found.
|
56
|
+
# Returns nil if no match is found.
|
57
|
+
def find(entity, id)
|
58
|
+
response = query(entity.to_s, id)
|
59
|
+
|
60
|
+
return nil if response.entities.empty?
|
61
|
+
|
62
|
+
response.entities.first
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param entity_type and value
|
66
|
+
# Other parameters, are optional.
|
67
|
+
# full set of parameters include entity_type, field, operation, value.
|
68
|
+
# Queries the Autotask QUERY API. Returns a QueryResponse result set.
|
69
|
+
# @return AutotaskRuby::Response.
|
70
|
+
def query(entity_type, field = 'id', operation = 'equals', value)
|
71
|
+
result = @soap_client.call(:query, message: "<sXML><![CDATA[<queryxml><entity>#{entity_type}</entity><query><field>#{field}<expression op=\"#{operation}\">#{value}</expression></field></query></queryxml>]]></sXML>")
|
72
|
+
AutotaskRuby::QueryResponse.new(self, result)
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param entity_type
|
76
|
+
# include the entity type. ServiceCall, Appointment, etc.
|
77
|
+
# @param ids
|
78
|
+
# One or more entity ID's that should be deleted.
|
79
|
+
# @return
|
80
|
+
# AutotaskRuby::DeleteResponse
|
81
|
+
def delete(entity_type, *ids)
|
82
|
+
entities = ++''
|
83
|
+
ids.each do |id|
|
84
|
+
entities << "<Entity xsi:type=\"#{entity_type}\"><id xsi:type=\"xsd:int\">#{id}</id></Entity>"
|
85
|
+
end
|
86
|
+
resp = @soap_client.call(:delete, message: "<Entities>#{entities.to_s}</Entities>")
|
87
|
+
AutotaskRuby::DeleteResponse.new(@client, resp)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module AutotaskRuby
|
2
|
+
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :integration_code
|
5
|
+
attr_accessor :version
|
6
|
+
attr_accessor :namespace
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@integration_code = nil
|
10
|
+
@version = 1.5
|
11
|
+
@namespace = 'http://autotask.net/ATWS/v1_5/'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def configuration
|
17
|
+
@configuration ||= Configuration.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure
|
21
|
+
yield(configuration)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AutotaskRuby
|
4
|
+
|
5
|
+
# Represents the Autotask Entity Contact
|
6
|
+
class Contact
|
7
|
+
include Entity
|
8
|
+
|
9
|
+
FIELDS = %i[id Active AddressLine City Country CreateDate EMailAddress Extension FirstName AccountID LastName MobilePhone Phone State Title ZipCode].freeze
|
10
|
+
.each do |field|
|
11
|
+
self.attr_accessor :"#{field.to_s.underscore}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_initialize
|
15
|
+
belongs_to :account
|
16
|
+
end
|
17
|
+
|
18
|
+
def full_name
|
19
|
+
[@first_name, @last_name].join(' ')
|
20
|
+
end
|
21
|
+
|
22
|
+
def email
|
23
|
+
@e_mail_address
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AutotaskRuby
|
4
|
+
# The base type for all objects represented by AutotaskRuby.
|
5
|
+
# This module should extend any object type being used with AutoTask.
|
6
|
+
module Entity
|
7
|
+
include AutotaskRuby::Constants
|
8
|
+
include AutotaskRuby::Association
|
9
|
+
|
10
|
+
FIELDS = %i[id].freeze
|
11
|
+
|
12
|
+
def self.included(base)
|
13
|
+
base.const_set :FIELDS, Entity::FIELDS unless base.const_defined?(:FIELDS)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(options = {})
|
17
|
+
@client = options if options.instance_of?(Client)
|
18
|
+
return unless options.kind_of?(Hash)
|
19
|
+
|
20
|
+
options.each do |k, v|
|
21
|
+
instance_variable_set("@#{k}", v)
|
22
|
+
end
|
23
|
+
|
24
|
+
post_initialize
|
25
|
+
end
|
26
|
+
|
27
|
+
# default post_initialize methods.
|
28
|
+
# Other classes that implement the Entity Class may override this.
|
29
|
+
def post_initialize
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
# Iterates the fields of a Entity Class Type.
|
34
|
+
# The fields are turned into instance variables.
|
35
|
+
# Fields could include id, StartDateTime, Title, etc.
|
36
|
+
def build(entity)
|
37
|
+
self.class.const_get(:FIELDS).each do |field|
|
38
|
+
instance_variable_set("@#{field}".underscore, field_set(entity, field))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# updates the entity in the AutoTask API.
|
43
|
+
# All fields are iterated and this builds the XML message that is sent to AutoTask.
|
44
|
+
# Any field that is not filled out will be sent as empty. This means that it will wipe
|
45
|
+
# any value that AutoTask has for that field.
|
46
|
+
def update
|
47
|
+
@client.soap_client.call(:update, message: "<Entity xsi:type=\"#{self.class.to_s.demodulize}\">#{fields_to_xml}</Entity>")
|
48
|
+
end
|
49
|
+
|
50
|
+
# creates an entity in AutoTask.
|
51
|
+
def create
|
52
|
+
result = @client.soap_client.call(:create, message: "<Entity xsi:type=\"#{self.class.to_s.demodulize}\">#{fields_to_xml}</Entity>")
|
53
|
+
CreateResponse.new(@client, result)
|
54
|
+
end
|
55
|
+
|
56
|
+
# converts the AutoTask dateTime string value to a ActiveSupport::TimeWithZone object.
|
57
|
+
# All dateTimes in AutoTask are in the Eastern Timezone.
|
58
|
+
def to_date_time(arg)
|
59
|
+
Time.find_zone!('Eastern Time (US & Canada)').parse(arg)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Converts the specified field in the AutoTask XML response to the entity object field/attribute.
|
63
|
+
# @param
|
64
|
+
# - entity
|
65
|
+
# - field
|
66
|
+
def field_set(entity, field)
|
67
|
+
node = entity.xpath("Autotask:#{field}", Autotask: AutotaskRuby.configuration.namespace)
|
68
|
+
|
69
|
+
# entity may not contain all fields that are possible.
|
70
|
+
# Example: The entity may not have a contact specified.
|
71
|
+
return if node.blank?
|
72
|
+
|
73
|
+
return node.text.to_i if node.attr('type').blank? || node.attr('type').text.eql?('xsd:int')
|
74
|
+
return to_date_time(node.text) if node.attr('type').text.eql?('xsd:dateTime')
|
75
|
+
return node.text.to_f if node.attr('type').text.eql?('xsd:double')
|
76
|
+
return node.text.to_f if node.attr('type').text.eql?('xsd:decimal')
|
77
|
+
|
78
|
+
node.text
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_bool(arg)
|
82
|
+
return true if arg == true || arg =~ (/(true|t|yes|y|1)$/i)
|
83
|
+
return false if arg == false || arg.empty? || arg =~ (/(false|f|no|n|0)$/i)
|
84
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{arg}\"")
|
85
|
+
end
|
86
|
+
|
87
|
+
# converts the entity attributes to XML representation.
|
88
|
+
# This is used when sending the object to the AutoTask API.
|
89
|
+
def fields_to_xml
|
90
|
+
str = ++''
|
91
|
+
|
92
|
+
self.class.const_get(:FIELDS).each do |field|
|
93
|
+
obj = instance_variable_get("@#{field}".underscore)
|
94
|
+
next unless obj
|
95
|
+
|
96
|
+
str << format_field_to_xml(field, obj)
|
97
|
+
end
|
98
|
+
str
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns the specified field as an XML element for the XML Body.
|
102
|
+
# I.E. <id>xxx</id>
|
103
|
+
# @param field_name
|
104
|
+
# the field name
|
105
|
+
# @param field_value
|
106
|
+
# the field value.
|
107
|
+
def format_field_to_xml(field_name, field_value)
|
108
|
+
return "<#{field_name}>#{field_value.strftime(AUTOTASK_TIME_FORMAT)}</#{field_name}>" if field_value.instance_of?(ActiveSupport::TimeWithZone)
|
109
|
+
|
110
|
+
"<#{field_name}>#{field_value}</#{field_name}>"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|