Class: Cherby::Cherwell

Inherits:
Object
  • Object
show all
Defined in:
lib/cherby/cherwell.rb

Overview

Top-level Cherwell interface

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(web_service_url, username = nil, password = nil) ⇒ Cherwell

Connect to a Cherwell server.

Parameters:

  • web_service_url (String)

    Full URL to the Cherwell web service API (typically ending in api.asmx)

  • username (String) (defaults to: nil)

    Default Cherwell user ID to use

  • password (String) (defaults to: nil)

    Default Cherwell password to use


23
24
25
26
27
28
29
# File 'lib/cherby/cherwell.rb', line 23

def initialize(web_service_url, username=nil, password=nil)
  @url = web_service_url
  @url.chop! if @url =~ /\/$/   # Remove any trailing slash
  @username = username
  @password = password
  @client = Cherby::Client.new(@url)
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client


11
12
13
# File 'lib/cherby/cherwell.rb', line 11

def client
  @client
end

#urlObject (readonly)

Returns the value of attribute url


11
12
13
# File 'lib/cherby/cherwell.rb', line 11

def url
  @url
end

#usernameObject (readonly)

Returns the value of attribute username


11
12
13
# File 'lib/cherby/cherwell.rb', line 11

def username
  @username
end

Instance Method Details

#create_incident(data) ⇒ Incident?

Create a new Cherwell incident with the given data. If creation succeeds, return the Incident instance; otherwise, return nil.

Examples:

create_incident(
  :service => 'Consulting Services',
  :sub_category => 'New/Modified Functionality',
  :priority => '4',
)

Parameters:

  • data (Hash)

    Incident fields to initialize. All required fields must be filled in, or creation will fail. At minimum this includes :service, :sub_category, and :priority.

Returns:

  • (Incident, nil)

    The created incident, or nil if creation failed.


230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/cherby/cherwell.rb', line 230

def create_incident(data)
  incident = Incident.create(data)
  result = @client.create_business_object({
    :busObNameOrId => 'Incident',
    :creationXml => incident.to_xml
  })

  # Result contains the public ID of the new incident, or nil if the
  # incident-creation failed.
  if !result.nil?
    incident['IncidentID'] = result
    return incident
  else
    return nil
  end
end

#get_business_object(object_type, id) ⇒ Object

Get a BusinessObject instance


177
178
179
180
# File 'lib/cherby/cherwell.rb', line 177

def get_business_object(object_type, id)
  xml = self.get_object_xml(object_type, id)
  return BusinessObject.new(xml)
end

#get_object_definition(object_type) ⇒ Object

Get a business object definition as a hash ex. get_object_definition('Incident')

TODO: Use this as the basis for building templates?


262
263
264
265
266
267
268
269
270
# File 'lib/cherby/cherwell.rb', line 262

def get_object_definition(object_type)
  result = {}
  definition = @client.get_business_object_definition(object_type)
  selector = 'BusinessObjectDef > FieldList > Field'
  Nokogiri::XML(definition).css(selector).map do |field|
    result[field['Name']] = field.css('Description').inner_html
  end
  return result
end

#get_object_xml(object_type, id) ⇒ String

Get a business object based on its public ID or RecID, and return the XML response.

This invokes GetBusinessObject or GetBusinessObjectByPublicId, depending on the length of id. The returned XML is the content of the GetBusinessObjectResult or GetBusinessObjectByPublicIdResult.

Examples:

incident_xml = cherwell.get_object_xml(
  'Incident', '12345')

note_xml = cherwell.get_object_xml(
  'JournalNote', '93bd7e3e067f1dafb454d14cb399dda1ef3f65d36d')

Parameters:

  • object_type (String)

    What type of object to fetch, for example "Incident", "Customer", "Task", "JournalNote", "SLA" etc. May also be the IDREF of an object type. Cherwell's API knows this as busObNameOrId.

  • id (String)

    The public ID or RecID of the object. If this is 32 characters or more, it's assumed to be a RecID. For incidents, the public ID is a numeric identifier like "50629", while the RecID is a long hexadecimal string like "93bd7e3e067f1dafb454d14cb399dda1ef3f65d36d".

Returns:

  • (String)

    Raw XML response string.

Raises:


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/cherby/cherwell.rb', line 152

def get_object_xml(object_type, id)
  # Assemble the SOAP body
  body = {:busObNameOrId => object_type}

  # If ID is really long, it's probably a RecID
  if id.to_s.length >= 32
    method = :get_business_object
    body[:busObRecId] = id
  # Otherwise, assume it's a public ID
  else
    method = :get_business_object_by_public_id
    body[:busObPublicId] = id
  end

  begin
    result = @client.call_wrap(method, body)
  rescue Savon::SOAPFault => e
    raise Cherby::SoapError.new(
      "SOAPFault from method '#{method}'", e.http)
  else
    return result.to_s
  end
end

#incident(id) ⇒ Incident

Get the Cherwell incident with the given public ID, and return an Incident object.

Returns:

Raises:

  • (Cherby::NotFound)

    If an error occurs when fetching the incident. The message attribute includes the error from Cherwell.


93
94
95
96
97
98
99
100
101
# File 'lib/cherby/cherwell.rb', line 93

def incident(id)
  incident_xml = get_object_xml('Incident', id)
  error = self.last_error
  if error
    raise Cherby::NotFound.new("Cannot find Incident '#{id}': #{error}")
  else
    return Incident.new(incident_xml.to_s)
  end
end

#last_errorString?

Get the last error reported by Cherwell.

Returns:

  • (String, nil)

    Text of the last error that occurred, or nil if there was no error.


252
253
254
# File 'lib/cherby/cherwell.rb', line 252

def last_error
  return @client.get_last_error
end

#login(username = nil, password = nil) ⇒ Boolean

Login to Cherwell using the given credentials. Return true if login succeeded, or raise LoginFailed if login failed.

Parameters:

  • username (String) (defaults to: nil)

    User ID to login with. If omitted, the username that was passed to Cherwell.new is used.

  • password (String) (defaults to: nil)

    Password to login with. If omitted, the password that was passed to Cherwell.new is used.

Returns:

  • (Boolean)

    true if login was successful

Raises:


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/cherby/cherwell.rb', line 47

def (username=nil, password=nil)
  creds = {
    :userId => username || @username,
    :password => password || @password,
  }
  begin
    response = @client.call(:login, :message => creds)
  rescue => e
    # This can happen if a bad URL is given
    raise Cherby::LoginFailed, e.message
  end

  # This can happen if invalid credentials are given
  if response.body[:login_response][:login_result] == false
    raise Cherby::LoginFailed, "Cherwell returned false status"
  end

  # Store cookies so subsequent requests will be authorized
  @client.cookies = response.http.cookies

  # Double-check that login worked
  if self.last_error
    raise Cherby::LoginFailed, "Cherwell returned error: '#{self.last_error}'"
  end

  return true
end

#logoutBoolean

Log out of Cherwell.

Returns:

  • (Boolean)

    Logout response as reported by Cherwell.


80
81
82
# File 'lib/cherby/cherwell.rb', line 80

def logout
  return @client.logout
end

#save_incident(incident) ⇒ Object

Save the given Cherwell incident


203
204
205
# File 'lib/cherby/cherwell.rb', line 203

def save_incident(incident)
  update_object_xml('Incident', incident.id, incident.to_xml)
end

#save_task(task) ⇒ Object

Save the given Cherwell task


208
209
210
# File 'lib/cherby/cherwell.rb', line 208

def save_task(task)
  update_object_xml('Task', task.id, task.to_xml)
end

#task(id) ⇒ Task

Get the Cherwell task with the given public ID, and return a Task object.

Returns:

Raises:

  • (Cherby::NotFound)

    If an error occurs when fetching the task. The message attribute includes the error from Cherwell.


112
113
114
115
116
117
118
119
120
# File 'lib/cherby/cherwell.rb', line 112

def task(id)
  task_xml = get_object_xml('Task', id)
  error = self.last_error
  if error
    raise Cherby::NotFound.new("Cannot find Task '#{id}': #{error}")
  else
    return Task.new(task_xml.to_s)
  end
end

#update_object_xml(object_type, id, xml) ⇒ Object

Update a given Cherwell object by submitting its XML to the SOAP interface.

Parameters:

  • object_type (String)

    The kind of object you're updating ('Incident', 'Task'), or the IDREF of the object type.

  • id (String)

    The public ID of the object

  • xml (String)

    The XML body containing all the updates you want to make


193
194
195
196
197
198
199
200
# File 'lib/cherby/cherwell.rb', line 193

def update_object_xml(object_type, id, xml)
  @client.update_business_object_by_public_id({
    :busObNameOrId => object_type,
    :busObPublicId => id,
    :updateXml => xml
  })
  return last_error
end