pjdavis-roart 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.
- data/History.txt +2 -0
- data/README.rdoc +66 -0
- data/Rakefile +35 -0
- data/lib/roart/connection.rb +54 -0
- data/lib/roart/core/array.rb +11 -0
- data/lib/roart/core/string.rb +18 -0
- data/lib/roart/errors.rb +11 -0
- data/lib/roart/roart.rb +11 -0
- data/lib/roart/ticket.rb +280 -0
- data/lib/roart/ticket_page.rb +38 -0
- data/lib/roart.rb +49 -0
- data/roart.gemspec +38 -0
- data/spec/roart/connection_spec.rb +7 -0
- data/spec/roart/core/array_spec.rb +13 -0
- data/spec/roart/core/string_spec.rb +13 -0
- data/spec/roart/roart_spec.rb +11 -0
- data/spec/roart/ticket_page_spec.rb +49 -0
- data/spec/roart/ticket_spec.rb +299 -0
- data/spec/roart_spec.rb +8 -0
- data/spec/spec_helper.rb +22 -0
- data/test/test_roart.rb +0 -0
- metadata +95 -0
data/History.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
== Roart
|
2
|
+
|
3
|
+
\___\__o/
|
4
|
+
/ \
|
5
|
+
|
6
|
+
|
7
|
+
by PJ Davis
|
8
|
+
http://github.com/pjdavis/roart
|
9
|
+
|
10
|
+
== DESCRIPTION:
|
11
|
+
If you are using Best Practical's Request Tracker (RT) and you need to interact with tickets from other applications, Roart provides an interface that is slightly reminiscent of ActiveRecord.
|
12
|
+
|
13
|
+
|
14
|
+
== FEATURES/PROBLEMS:
|
15
|
+
|
16
|
+
* Access RT Tickets through an ActiveRecord like API
|
17
|
+
|
18
|
+
* This has only been tested against RT 3.6. Changes to the REST interface in later versions of RT may break stuff.
|
19
|
+
|
20
|
+
== SYNOPSIS:
|
21
|
+
|
22
|
+
* Create a class to interact with your ticket system
|
23
|
+
|
24
|
+
require 'rubygems'
|
25
|
+
require 'roart'
|
26
|
+
|
27
|
+
class Ticket < Roart::Ticket
|
28
|
+
connection :server => 'http://my.rt.server.com', :user => 'myuser', :pass => 'mypass'
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
* Search for tickets
|
33
|
+
|
34
|
+
my_tickets = Ticket.find(:all, :queue => 'Scutters', :status => [:new, :open])
|
35
|
+
my_tickets.each do |ticket|
|
36
|
+
puts ticket.subject
|
37
|
+
end
|
38
|
+
|
39
|
+
#-> New John Wayne packages
|
40
|
+
#-> Medi-lab training
|
41
|
+
|
42
|
+
* See all info for a ticket
|
43
|
+
|
44
|
+
my_ticket = Ticket.find(:first, :queue => 'Issues', :status => :new)
|
45
|
+
ticket.creator #-> rimmer@reddwarf.com
|
46
|
+
ticket.subject #-> Where is the Bomb?
|
47
|
+
|
48
|
+
|
49
|
+
== REQUIREMENTS:
|
50
|
+
|
51
|
+
* mechanize
|
52
|
+
* A working RT3 install.
|
53
|
+
|
54
|
+
== INSTALL:
|
55
|
+
|
56
|
+
$ gem sources -a http://gems.github.com
|
57
|
+
$ sudo gem install pjdavis-roart
|
58
|
+
|
59
|
+
== LICENSE:
|
60
|
+
|
61
|
+
(C) PJ Davis <pj.davis@gmail.com>
|
62
|
+
|
63
|
+
This program is free software; you can redistribute it and/or modify it under
|
64
|
+
the terms of the WTFPL, Version 2, as
|
65
|
+
published by Sam Hocevar. See http://sam.zoy.org/wtfpl/ for more details.
|
66
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
begin
|
10
|
+
load 'tasks/setup.rb'
|
11
|
+
rescue LoadError
|
12
|
+
raise RuntimeError, '### please install the "bones" gem ###'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ensure_in_path 'lib'
|
17
|
+
require 'roart'
|
18
|
+
|
19
|
+
task :default => 'spec:run'
|
20
|
+
|
21
|
+
PROJ.name = 'roart'
|
22
|
+
PROJ.ignore_file = '.gitignore'
|
23
|
+
PROJ.authors = 'PJ Davis'
|
24
|
+
PROJ.email = 'pj.davis@gmail.com'
|
25
|
+
PROJ.url = 'http://github.com/pjdavis/roart'
|
26
|
+
PROJ.version = Roart::VERSION
|
27
|
+
PROJ.rubyforge.name = 'roart'
|
28
|
+
PROJ.exclude = %w(.git pkg coverage)
|
29
|
+
PROJ.description = "Interface for working with Request Tracker (RT) tickets inspired by ActiveRecord."
|
30
|
+
PROJ.rdoc.main = 'README.rdoc'
|
31
|
+
depend_on 'mechanize'
|
32
|
+
|
33
|
+
PROJ.spec.opts << '--color'
|
34
|
+
|
35
|
+
# EOF
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'mechanize'
|
3
|
+
|
4
|
+
module Roart
|
5
|
+
|
6
|
+
module Connections
|
7
|
+
RequiredConfig = %w(server user pass)
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
class Connection
|
12
|
+
|
13
|
+
attr_reader :agent
|
14
|
+
|
15
|
+
def initialize(conf)
|
16
|
+
|
17
|
+
if conf.is_a?(String)
|
18
|
+
raise "Loading Config File not yet implemented"
|
19
|
+
elsif conf.is_a?(Hash)
|
20
|
+
Roart::check_keys!(conf, Roart::Connections::RequiredConfig)
|
21
|
+
@conf = conf
|
22
|
+
end
|
23
|
+
|
24
|
+
@agent = login
|
25
|
+
add_methods!
|
26
|
+
end
|
27
|
+
|
28
|
+
def get(uri)
|
29
|
+
@agent.get(uri).body
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def login
|
35
|
+
agent = WWW::Mechanize.new
|
36
|
+
page = agent.get(@conf[:server])
|
37
|
+
form = page.form('login')
|
38
|
+
form.user = @conf[:user]
|
39
|
+
form.pass = @conf[:pass]
|
40
|
+
page = agent.submit form
|
41
|
+
agent
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_methods!
|
45
|
+
@conf.each do |key, value|
|
46
|
+
(class << self; self; end).send :define_method, key do
|
47
|
+
return value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# used from ActiveSupport
|
2
|
+
# Copyright (c) 2005-2009 David Heinemeier Hansson
|
3
|
+
|
4
|
+
class String
|
5
|
+
|
6
|
+
def underscore
|
7
|
+
self.gsub(/::/, '/').
|
8
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
9
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
10
|
+
tr("-", "_").
|
11
|
+
downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
def camelize
|
15
|
+
self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/roart/errors.rb
ADDED
data/lib/roart/roart.rb
ADDED
data/lib/roart/ticket.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
module Roart
|
2
|
+
|
3
|
+
module Tickets
|
4
|
+
|
5
|
+
DefaultAttributes = %w(queue owner creator subject status priority initial_priority final_priority requestors cc admin_cc created starts started due resolved told last_updated time_estimated time_worked time_left full logs)
|
6
|
+
RequiredAttributes = %w(queue creator subject status created)
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class Ticket
|
11
|
+
|
12
|
+
def initialize(attributes)
|
13
|
+
Roart::check_keys!(attributes, Roart::Tickets::RequiredAttributes)
|
14
|
+
if attributes.is_a?(Hash)
|
15
|
+
@attributes = Roart::Tickets::DefaultAttributes.to_hash.merge(attributes)
|
16
|
+
else
|
17
|
+
raise ArgumentError, "Expects a hash."
|
18
|
+
end
|
19
|
+
add_methods!
|
20
|
+
end
|
21
|
+
|
22
|
+
# Loads all information for a ticket from RT and lets full to true.
|
23
|
+
# This changes the ticket object and adds methods for all the fields on the ticket.
|
24
|
+
# Custom fields will be prefixed with 'cf' so a custom field of 'phone'
|
25
|
+
# would be cf_phone
|
26
|
+
#
|
27
|
+
def load_full!
|
28
|
+
unless self.full
|
29
|
+
ticket = self.class.find(self.id)
|
30
|
+
@attributes = ticket.instance_variable_get("@attributes")
|
31
|
+
add_methods!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self #class methods
|
36
|
+
|
37
|
+
# Gives or Sets the connection object for the RT Server.
|
38
|
+
# Accepts 3 parameters :server, :user, and :pass. Call this
|
39
|
+
# at the top of your subclass to create the connection,
|
40
|
+
# class Ticket < Roart::Ticket
|
41
|
+
# connection :server => 'server', :user => 'user', :pass => 'pass'
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
def connection(options=nil)
|
45
|
+
if options && @connection.nil?
|
46
|
+
@connection = Roart::Connection.new(options)
|
47
|
+
else
|
48
|
+
@connection
|
49
|
+
end
|
50
|
+
@connection
|
51
|
+
end
|
52
|
+
|
53
|
+
# Searches for a ticket or group of tickets with an active
|
54
|
+
# record like interface.
|
55
|
+
#
|
56
|
+
# Find has 3 different ways to search for tickets
|
57
|
+
#
|
58
|
+
# * search for tickets by the id. This will search for the Ticket with the exact id and will automatically load the entire ticket into the object (full will return true).
|
59
|
+
# * search for all tickets with a hash for search options by specifying :all along with your options. This will return an array of tickets or an empty array if no tickets are found that match the options.
|
60
|
+
# * search for a single ticket with a hash for search options by specifying :first along with your options. This will return a single ticket object or nil if no tickets are found.
|
61
|
+
#
|
62
|
+
# A hash of options for search paramaters are passed in as the last argument.
|
63
|
+
#
|
64
|
+
# ====Parameters
|
65
|
+
# * <tt>:queue</tt> or <tt>:queues</tt> - the name of a queue in the ticket system. This can be specified as a string, a symbol or an array of strings or symbols. The array will search for tickets included in either queue.
|
66
|
+
# * <tt>:status</tt> - the status of the tickets to search for. This can be specified as a string, a symbol or an array of strings or symbols.
|
67
|
+
# * <tt>:subject</tt>, <tt>:content</tt>, <tt>content_type</tt>, <tt>file_name</tt> - takes a string and searches for that string in the respective field.
|
68
|
+
# * <tt>:created</tt>, <tt>:started</tt>, <tt>:resolved</tt>, <tt>:told</tt>, <tt>:last_updated</tt>, <tt>:starts</tt>, <tt>:due</tt>, <tt>:updated</tt> - looks for dates for the respective fields. Can take a Range, Array, String, Time. Range will find all tickets between the two dates (after the first, before the last). Array works the same way, using #first and #last on the array. The elements should be either db-time formatted strings or Time objects. Time will be formatted as a db string. String will be passed straight to the search.
|
69
|
+
# * <tt>:custom_fields</tt> - takes a hash of custom fields to search for. the key should be the name of the field exactly how it is in RT and the value will be what to search for.
|
70
|
+
#
|
71
|
+
# ==== Examples
|
72
|
+
#
|
73
|
+
# # find first
|
74
|
+
# MyTicket.find(:first)
|
75
|
+
# MyTicket.find(:first, :queue => 'My Queue')
|
76
|
+
# MyTicket.find(:first, :status => [:new, :open])
|
77
|
+
# MyTicket.find(:first, :queue => 'My Queue', :status => :resolved)
|
78
|
+
# MyTicket.find(:first, :custom_fields => {:phone => '8675309'})
|
79
|
+
#
|
80
|
+
# # find all
|
81
|
+
# MyTicket.find(:all, :subject => 'is down')
|
82
|
+
# MyTicket.find(:all, :created => [Time.now - 300, Time.now])
|
83
|
+
# MyTicket.find(:all, :queues => ['my queue', 'issues'])
|
84
|
+
#
|
85
|
+
# # find by id
|
86
|
+
# MyTicket.find(12345)
|
87
|
+
#
|
88
|
+
def find(*args)
|
89
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
90
|
+
case args.first
|
91
|
+
when :first then find_initial(options)
|
92
|
+
when :all then find_all(options)
|
93
|
+
else find_by_ids(args, options)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
def instantiate(ticket)
|
100
|
+
object = nil
|
101
|
+
if ticket.is_a?(Array)
|
102
|
+
array = Array.new
|
103
|
+
ticket.each do |tick|
|
104
|
+
object = self.allocate
|
105
|
+
object.instance_variable_set("@attributes", tick)
|
106
|
+
object.send("add_methods!")
|
107
|
+
array << object
|
108
|
+
end
|
109
|
+
return array
|
110
|
+
elsif ticket.is_a?(Hash)
|
111
|
+
object = self.allocate
|
112
|
+
object.instance_variable_set("@attributes", ticket)
|
113
|
+
object.send("add_methods!")
|
114
|
+
end
|
115
|
+
object
|
116
|
+
end
|
117
|
+
|
118
|
+
def find_initial(options={})
|
119
|
+
options.update(:limit => 1)
|
120
|
+
find_all(options).first
|
121
|
+
end
|
122
|
+
|
123
|
+
def find_all(options)
|
124
|
+
uri = construct_search_uri(options)
|
125
|
+
tickets = get_tickets_from_search_uri(uri)
|
126
|
+
end
|
127
|
+
|
128
|
+
def find_by_ids(args, options)
|
129
|
+
get_ticket_by_id(args.first)
|
130
|
+
end
|
131
|
+
|
132
|
+
def page_array(uri)
|
133
|
+
page = self.connection.get(uri)
|
134
|
+
raise TicketSystemError, "Can't get ticket." unless page
|
135
|
+
page = page.split("\n")
|
136
|
+
status = page.delete_at(0)
|
137
|
+
if status.include?("200")
|
138
|
+
page.delete_if{|x| !x.include?(":")}
|
139
|
+
page
|
140
|
+
else
|
141
|
+
raise TicketSystemInterfaceError, "Error Getting Ticket: #{status}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def get_tickets_from_search_uri(uri)
|
146
|
+
page = page_array(uri)
|
147
|
+
page.extend(Roart::TicketPage)
|
148
|
+
page = page.to_search_array
|
149
|
+
self.instantiate(page)
|
150
|
+
end
|
151
|
+
|
152
|
+
def get_ticket_from_uri(uri)
|
153
|
+
page = page_array(uri)
|
154
|
+
page.extend(Roart::TicketPage)
|
155
|
+
page = page.to_hash
|
156
|
+
page.update(:full => true)
|
157
|
+
self.instantiate(page)
|
158
|
+
end
|
159
|
+
|
160
|
+
def get_ticket_by_id(id)
|
161
|
+
uri = "#{self.connection.server}/REST/1.0/ticket/"
|
162
|
+
uri << id.to_s
|
163
|
+
get_ticket_from_uri(uri)
|
164
|
+
end
|
165
|
+
|
166
|
+
def construct_search_uri(options)
|
167
|
+
uri = "#{self.connection.server}/REST/1.0/search/ticket?"
|
168
|
+
uri << 'orderby=-Created&' if options.delete(:order)
|
169
|
+
unless options.empty?
|
170
|
+
uri << 'query= '
|
171
|
+
query = Array.new
|
172
|
+
|
173
|
+
add_queue!(query, options[:queues] || options[:queue])
|
174
|
+
add_dates!(query, options)
|
175
|
+
add_searches!(query, options)
|
176
|
+
add_status!(query, options[:status])
|
177
|
+
add_custom_fields!(query, options[:custom_fields])
|
178
|
+
|
179
|
+
query << options[:conditions].to_s.chomp if options[:conditions]
|
180
|
+
|
181
|
+
uri << query.join(" AND ")
|
182
|
+
end
|
183
|
+
uri
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_queue!(uri, queue)
|
187
|
+
return false unless queue
|
188
|
+
if queue.is_a?(Array)
|
189
|
+
queues = Array.new
|
190
|
+
queue.each do |name|
|
191
|
+
queues << "Queue = '#{name}'"
|
192
|
+
end
|
193
|
+
uri << '( ' + queues.join(' OR ') + ' )'
|
194
|
+
elsif queue.is_a?(String) || queue.is_a?(Symbol)
|
195
|
+
uri << "Queue = '#{queue.to_s}'"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def add_custom_fields!(uri, options)
|
200
|
+
return false unless options
|
201
|
+
options.each do |field, value|
|
202
|
+
if value.is_a?(Array)
|
203
|
+
valpart = Array.new
|
204
|
+
for val in value
|
205
|
+
valpart << "'CF.{#{field}}' = '#{val.to_s}'"
|
206
|
+
end
|
207
|
+
uri << '( ' + valpart.join(" OR ") + ' )'
|
208
|
+
elsif value.is_a?(String)
|
209
|
+
uri << "'CF.{#{field}}' = '#{value.to_s}'"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def add_status!(uri, options)
|
215
|
+
return false unless options
|
216
|
+
parts = Array.new
|
217
|
+
if options.is_a?(Array)
|
218
|
+
statpart = Array.new
|
219
|
+
for status in options
|
220
|
+
statpart << "Status = '#{status.to_s}'"
|
221
|
+
end
|
222
|
+
parts << '( ' + statpart.join(" OR ") + ' )'
|
223
|
+
elsif options.is_a?(String) || options.is_a?(Symbol)
|
224
|
+
parts << "Status = '#{options.to_s}'"
|
225
|
+
end
|
226
|
+
uri << parts
|
227
|
+
end
|
228
|
+
|
229
|
+
def add_searches!(uri, options)
|
230
|
+
search_fields = %w( subject content content_type file_name)
|
231
|
+
options.each do |key, value|
|
232
|
+
if search_fields.include?(key.to_s)
|
233
|
+
key = key.to_s.camelize
|
234
|
+
parts = Array.new
|
235
|
+
if value.is_a?(Array)
|
236
|
+
value.each do |v|
|
237
|
+
parts << "#{key} LIKE '#{v}'"
|
238
|
+
end
|
239
|
+
uri << '( ' + parts.join(" AND ") + ' )'
|
240
|
+
elsif value.is_a?(String)
|
241
|
+
uri << "#{key} LIKE '#{value}'"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def add_dates!(uri, options)
|
248
|
+
date_field = %w( created started resolved told last_updated starts due updated )
|
249
|
+
options.each do |key, value|
|
250
|
+
if date_field.include?(key.to_s)
|
251
|
+
key = key.to_s.camelize
|
252
|
+
parts = Array.new
|
253
|
+
if value.is_a?(Range) or value.is_a?(Array)
|
254
|
+
parts << "#{key} > '#{value.first.is_a?(Time) ? value.first.strftime("%Y-%m-%d %H:%M:%S") : value.first.to_s}'"
|
255
|
+
parts << "#{key} < '#{value.last.is_a?(Time) ? value.last.strftime("%Y-%m-%d %H:%M:%S") : value.last.to_s}'"
|
256
|
+
elsif value.is_a?(String)
|
257
|
+
parts << "#{key} > '#{value.to_s}'"
|
258
|
+
elsif value.is_a?(Time)
|
259
|
+
parts << "#{key} > '#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
|
260
|
+
end
|
261
|
+
uri << '( ' + parts.join(" AND ") + ' )'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
protected
|
269
|
+
|
270
|
+
def add_methods!
|
271
|
+
@attributes.each do |key, value|
|
272
|
+
(class << self; self; end).send :define_method, key do
|
273
|
+
return value
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Roart
|
2
|
+
|
3
|
+
module TicketPage
|
4
|
+
|
5
|
+
def to_hash
|
6
|
+
hash = Hash.new
|
7
|
+
self.delete_if{|x| !x.include?(":")}
|
8
|
+
self.each do |ln|
|
9
|
+
ln = ln.split(":")
|
10
|
+
key = ln.delete_at(0).strip.underscore
|
11
|
+
value = ln.join(":").strip
|
12
|
+
hash[key.to_sym] = value
|
13
|
+
end
|
14
|
+
hash[:id] = hash[:id].split("/").last.to_i
|
15
|
+
hash.update(:history => false)
|
16
|
+
hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_search_array
|
20
|
+
array = Array.new
|
21
|
+
self.delete_if{|x| !x.include?(":")}
|
22
|
+
self.each do |ln|
|
23
|
+
hash = Hash.new
|
24
|
+
ln = ln.split(":")
|
25
|
+
id = ln.delete_at(0).strip.underscore
|
26
|
+
sub = ln.join(":").strip
|
27
|
+
hash[:id] = id.to_i
|
28
|
+
hash[:subject] = sub
|
29
|
+
hash[:full] = false
|
30
|
+
hash[:history] = false
|
31
|
+
array << hash
|
32
|
+
end
|
33
|
+
array
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/roart.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
module Roart
|
3
|
+
|
4
|
+
# :stopdoc:
|
5
|
+
VERSION = '0.1.0'
|
6
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
7
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
8
|
+
# :startdoc:
|
9
|
+
|
10
|
+
# Returns the version string for the library.
|
11
|
+
#
|
12
|
+
def self.version
|
13
|
+
VERSION
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the library path for the module. If any arguments are given,
|
17
|
+
# they will be joined to the end of the libray path using
|
18
|
+
# <tt>File.join</tt>.
|
19
|
+
#
|
20
|
+
def self.libpath( *args )
|
21
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the lpath for the module. If any arguments are given,
|
25
|
+
# they will be joined to the end of the path using
|
26
|
+
# <tt>File.join</tt>.
|
27
|
+
#
|
28
|
+
def self.path( *args )
|
29
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Utility method used to require all files ending in .rb that lie in the
|
33
|
+
# directory below this file that has the same name as the filename passed
|
34
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
35
|
+
# the _filename_ does not have to be equivalent to the directory.
|
36
|
+
#
|
37
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
38
|
+
dir ||= ::File.basename(fname, '.*')
|
39
|
+
search_me = ::File.expand_path(
|
40
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
41
|
+
|
42
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
43
|
+
end
|
44
|
+
|
45
|
+
end # module Roart
|
46
|
+
|
47
|
+
Roart.require_all_libs_relative_to(__FILE__)
|
48
|
+
|
49
|
+
# EOF
|
data/roart.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{roart}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["PJ Davis"]
|
9
|
+
s.date = %q{2009-08-14}
|
10
|
+
s.description = %q{Interface for working with Request Tracker (RT) tickets inspired by ActiveRecord.}
|
11
|
+
s.email = %q{pj.davis@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["History.txt", "README.rdoc"]
|
13
|
+
s.files = ["History.txt", "README.rdoc", "Rakefile", "lib/roart.rb", "lib/roart/connection.rb", "lib/roart/core/array.rb", "lib/roart/core/string.rb", "lib/roart/errors.rb", "lib/roart/roart.rb", "lib/roart/ticket.rb", "lib/roart/ticket_page.rb", "roart.gemspec", "spec/roart/connection_spec.rb", "spec/roart/core/array_spec.rb", "spec/roart/core/string_spec.rb", "spec/roart/roart_spec.rb", "spec/roart/ticket_page_spec.rb", "spec/roart/ticket_spec.rb", "spec/roart_spec.rb", "spec/spec_helper.rb", "test/test_roart.rb"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/pjdavis/roart}
|
16
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{roart}
|
19
|
+
s.rubygems_version = %q{1.3.2}
|
20
|
+
s.summary = %q{Interface for working with Request Tracker (RT) tickets inspired by ActiveRecord}
|
21
|
+
s.test_files = ["test/test_roart.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_runtime_dependency(%q<mechanize>, [">= 0.9.0"])
|
29
|
+
s.add_development_dependency(%q<bones>, [">= 2.5.1"])
|
30
|
+
else
|
31
|
+
s.add_dependency(%q<mechanize>, [">= 0.9.0"])
|
32
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
33
|
+
end
|
34
|
+
else
|
35
|
+
s.add_dependency(%q<mechanize>, [">= 0.9.0"])
|
36
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[ .. .. spec_helper])
|
2
|
+
|
3
|
+
describe 'array extentions' do
|
4
|
+
|
5
|
+
it 'should turn an array to a nil valued hash' do
|
6
|
+
array = %w[key1 key2]
|
7
|
+
hash = array.to_hash
|
8
|
+
hash.has_key?(:key1).should be_true
|
9
|
+
hash.has_key?(:key2).should be_true
|
10
|
+
hash[:key1].should be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[ .. .. spec_helper])
|
2
|
+
|
3
|
+
describe 'string extentions' do
|
4
|
+
|
5
|
+
it 'should underscore a word' do
|
6
|
+
'SomeGuy'.underscore.should == 'some_guy'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should camelcase a word' do
|
10
|
+
'some_guy'.camelize.should == 'SomeGuy'
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[ .. spec_helper])
|
3
|
+
|
4
|
+
describe "Roart" do
|
5
|
+
|
6
|
+
it "should raise an error if there aren't required fields" do
|
7
|
+
attributes = {:subject => "Not Enough Stuff"}
|
8
|
+
lambda { Roart::check_keys!(attributes, Roart::Tickets::RequiredAttributes) }.should raise_error(Roart::ArgumentError)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[ .. spec_helper])
|
2
|
+
|
3
|
+
describe 'ticket page' do
|
4
|
+
|
5
|
+
describe 'ticket hash' do
|
6
|
+
|
7
|
+
it 'should convert an array to a hash' do
|
8
|
+
array = ["id : 10", "subject : asdf"]
|
9
|
+
array.extend(Roart::TicketPage)
|
10
|
+
hash = array.to_hash
|
11
|
+
hash.has_key?(:id).should be_true
|
12
|
+
hash[:id].should == 10
|
13
|
+
hash[:subject].should == 'asdf'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not have a history' do
|
17
|
+
array = ["id : 10", "subject : asdf"]
|
18
|
+
array.extend(Roart::TicketPage)
|
19
|
+
hash = array.to_hash
|
20
|
+
hash[:history].should be_false
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'search array' do
|
26
|
+
|
27
|
+
before do
|
28
|
+
@array = ["123 : Subject", "234 : Subject"]
|
29
|
+
@array.extend(Roart::TicketPage)
|
30
|
+
@array = @array.to_search_array
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should make an array of search results' do
|
34
|
+
@array.size.should == 2
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should put search elements into the search array' do
|
38
|
+
@array.first[:id].should == 123
|
39
|
+
@array.last[:id].should == 234
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should keep history false' do
|
43
|
+
@array.first[:history].should be_false
|
44
|
+
@array.last[:history].should be_false
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[ .. spec_helper])
|
2
|
+
|
3
|
+
describe "Ticket" do
|
4
|
+
|
5
|
+
it "should have a connection" do
|
6
|
+
Roart::Connection.should_receive(:new).with('some options').and_return(true)
|
7
|
+
Roart::Ticket.connection('some options').should == true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should find the first ticket" do
|
11
|
+
Roart::Ticket.should_receive(:find_initial).with(:my => 'options').and_return('a ticket')
|
12
|
+
Roart::Ticket.find(:first, :my => 'options').should == 'a ticket'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should find all tickets' do
|
16
|
+
Roart::Ticket.should_receive(:find_all).with(:my => 'options').and_return(%w[array of tickets])
|
17
|
+
Roart::Ticket.find(:all, :my => 'options').should == ['array', 'of', 'tickets']
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should find a ticket by id' do
|
21
|
+
Roart::Ticket.should_receive(:find_by_ids).with([12345],{}).and_return('a ticket')
|
22
|
+
Roart::Ticket.find(12345).should == 'a ticket'
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "find initial" do
|
26
|
+
|
27
|
+
it 'should set options to include :limit => 1' do
|
28
|
+
Roart::Ticket.should_receive(:find_all).with({:limit => 1}).and_return(['ticket', 'not seen'])
|
29
|
+
Roart::Ticket.send(:find_initial)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should not overwrite the options hash' do
|
33
|
+
Roart::Ticket.should_receive(:find_all).with({:queue => 'queue', :limit => 1}).and_return(['ticket', 'not seen'])
|
34
|
+
Roart::Ticket.send(:find_initial, :queue => 'queue')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should return 1 ticket object' do
|
38
|
+
Roart::Ticket.should_receive(:find_all).with({:limit => 1}).and_return(['ticket', 'not seen'])
|
39
|
+
Roart::Ticket.send(:find_initial).should == 'ticket'
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'page array' do
|
45
|
+
|
46
|
+
it 'should raise an error if not a 200 response' do
|
47
|
+
connection = mock('connection', :get => 'some error message')
|
48
|
+
Roart::Ticket.should_receive(:connection).and_return(connection)
|
49
|
+
lambda do
|
50
|
+
Roart::Ticket.send(:page_array, 'www.whatever')
|
51
|
+
end.should raise_error(Roart::TicketSystemInterfaceError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should raise an error if nothing is returned' do
|
55
|
+
connection = mock('connection', :get => nil)
|
56
|
+
Roart::Ticket.should_receive(:connection).and_return(connection)
|
57
|
+
lambda do
|
58
|
+
Roart::Ticket.send(:page_array, 'www.whatever')
|
59
|
+
end.should raise_error(Roart::TicketSystemError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should give back an array of strings' do
|
63
|
+
connection = mock('connection', :get => "200 OK\n23:SomeTicket\n33:Another")
|
64
|
+
Roart::Ticket.should_receive(:connection).and_return(connection)
|
65
|
+
Roart::Ticket.send(:page_array, 'uri').should == ['23:SomeTicket', '33:Another']
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'getting tickets from URI' do
|
71
|
+
|
72
|
+
describe 'search' do
|
73
|
+
|
74
|
+
it 'should give an array of tickets' do
|
75
|
+
Roart::Ticket.should_receive(:page_array).with('uri').and_return(['23:SomeTicket', '33:Another'])
|
76
|
+
Roart::Ticket.send(:get_tickets_from_search_uri, 'uri').size.should == 2
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should not have full tickets' do
|
80
|
+
Roart::Ticket.should_receive(:page_array).with('uri').and_return(['23:SomeTicket', '33:Another'])
|
81
|
+
Roart::Ticket.send(:get_tickets_from_search_uri, 'uri').each do |ticket|
|
82
|
+
ticket.full.should_not be_true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'full ticket' do
|
89
|
+
|
90
|
+
it 'should give a ticket' do
|
91
|
+
Roart::Ticket.should_receive(:page_array).with('uri').and_return(['id:23', 'subject:someticket'])
|
92
|
+
Roart::Ticket.send(:get_ticket_from_uri, 'uri').is_a?(Roart::Ticket).should be_true
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should be a full ticket' do
|
96
|
+
Roart::Ticket.should_receive(:page_array).with('uri').and_return(['id:23', 'subject:someticket'])
|
97
|
+
Roart::Ticket.send(:get_ticket_from_uri, 'uri').full.should be_true
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'getting ticket from id' do
|
103
|
+
|
104
|
+
it 'should give a ticket' do
|
105
|
+
connection = mock('connection', :server => "server")
|
106
|
+
Roart::Ticket.should_receive(:connection).and_return(connection)
|
107
|
+
Roart::Ticket.should_receive(:get_ticket_from_uri).with('server' + '/REST/1.0/ticket/' + 12345.to_s).and_return('a ticket')
|
108
|
+
Roart::Ticket.send(:get_ticket_by_id, 12345).should == 'a ticket'
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'find methods' do
|
114
|
+
|
115
|
+
it 'should get all tickets from an options hash' do
|
116
|
+
Roart::Ticket.should_receive('construct_search_uri').with('searches').and_return('uri')
|
117
|
+
Roart::Ticket.should_receive('get_tickets_from_search_uri').with('uri').and_return(['tickets'])
|
118
|
+
Roart::Ticket.send(:find_all, 'searches').should == ['tickets']
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should find tickets from id' do
|
122
|
+
Roart::Ticket.should_receive(:get_ticket_by_id).with('id').and_return('a ticket')
|
123
|
+
Roart::Ticket.send(:find_by_ids, ['id'], {}).should == 'a ticket'
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'building a search uri' do
|
129
|
+
|
130
|
+
before do
|
131
|
+
@connection = mock('connection', :server => "server")
|
132
|
+
@search_string = "/REST/1.0/search/ticket?"
|
133
|
+
Roart::Ticket.should_receive(:connection).and_return(@connection)
|
134
|
+
@query = @connection.server + @search_string + 'query= '
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'queues' do
|
138
|
+
|
139
|
+
it 'should include a queue' do
|
140
|
+
Roart::Ticket.send(:construct_search_uri, {:queue => 'myQueue'}).should == @query + "Queue = 'myQueue'"
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should take multiple queues' do
|
144
|
+
Roart::Ticket.send(:construct_search_uri, {:queue => ['myQueue', 'another']}).should == @query + "( Queue = 'myQueue' OR Queue = 'another' )"
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'dates' do
|
150
|
+
|
151
|
+
before do
|
152
|
+
@time = Time.now
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should accept a date' do
|
156
|
+
Roart::Ticket.send(:construct_search_uri, {:created => @time}).should == @query + "( Created > '#{dbtime(@time)}' )"
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should accept an array of dates' do
|
160
|
+
Roart::Ticket.send(:construct_search_uri, {:created => [@time, @time + 300]}).should == @query + "( Created > '#{dbtime(@time)}' AND Created < '#{dbtime(@time + 300)}' )"
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should accept a range of dates' do
|
164
|
+
Roart::Ticket.send(:construct_search_uri, {:created => (@time..(@time + 300))}).should == @query + "( Created > '#{dbtime(@time)}' AND Created < '#{dbtime(@time + 300)}' )"
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should accept an array of strings' do
|
168
|
+
Roart::Ticket.send(:construct_search_uri, {:created => %w[cat dog]}).should == @query + "( Created > 'cat' AND Created < 'dog' )"
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should accept a string' do
|
172
|
+
Roart::Ticket.send(:construct_search_uri, {:created => 'time'}).should == @query + "( Created > 'time' )"
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'date fields' do
|
176
|
+
|
177
|
+
it 'should search started' do
|
178
|
+
Roart::Ticket.send(:construct_search_uri, {:started => 'time'}).should == @query + "( Started > 'time' )"
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should search resolved' do
|
182
|
+
Roart::Ticket.send(:construct_search_uri, {:resolved => 'time'}).should == @query + "( Resolved > 'time' )"
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should search told' do
|
186
|
+
Roart::Ticket.send(:construct_search_uri, {:told => 'time'}).should == @query + "( Told > 'time' )"
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should search last_updated' do
|
190
|
+
Roart::Ticket.send(:construct_search_uri, {:last_updated => 'time'}).should == @query + "( LastUpdated > 'time' )"
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should search starts' do
|
194
|
+
Roart::Ticket.send(:construct_search_uri, {:starts => 'time'}).should == @query + "( Starts > 'time' )"
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should search due' do
|
198
|
+
Roart::Ticket.send(:construct_search_uri, {:due => 'time'}).should == @query + "( Due > 'time' )"
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should search updated' do
|
202
|
+
Roart::Ticket.send(:construct_search_uri, {:updated => 'time'}).should == @query + "( Updated > 'time' )"
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
describe 'searches' do
|
210
|
+
|
211
|
+
it 'should accept a string' do
|
212
|
+
Roart::Ticket.send(:construct_search_uri, {:subject => 'fish'}).should == @query + "Subject LIKE 'fish'"
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should accept an array' do
|
216
|
+
Roart::Ticket.send(:construct_search_uri, {:subject => %w[cramanation station]}).should == @query + "( Subject LIKE 'cramanation' AND Subject LIKE 'station' )"
|
217
|
+
end
|
218
|
+
|
219
|
+
describe 'search fields' do
|
220
|
+
|
221
|
+
it 'should search content' do
|
222
|
+
Roart::Ticket.send(:construct_search_uri, {:content => 'fish'}).should == @query + "Content LIKE 'fish'"
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should search content_type' do
|
226
|
+
Roart::Ticket.send(:construct_search_uri, {:content_type => 'fish'}).should == @query + "ContentType LIKE 'fish'"
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should search file_name' do
|
230
|
+
Roart::Ticket.send(:construct_search_uri, {:file_name => 'fish'}).should == @query + "FileName LIKE 'fish'"
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
describe 'status' do
|
238
|
+
|
239
|
+
it 'should accept a string' do
|
240
|
+
Roart::Ticket.send(:construct_search_uri, {:status => 'new'}).should == @query + "Status = 'new'"
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'should accept a symbol' do
|
244
|
+
Roart::Ticket.send(:construct_search_uri, {:status => :new}).should == @query + "Status = 'new'"
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'should accept an array' do
|
248
|
+
Roart::Ticket.send(:construct_search_uri, {:status => ['new', 'open']}).should == @query + "( Status = 'new' OR Status = 'open' )"
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
describe 'custom_fields' do
|
254
|
+
|
255
|
+
it 'should accept a hash with string values' do
|
256
|
+
Roart::Ticket.send(:construct_search_uri, {:custom_fields => {:phone => '8675309'}}).should == @query + "'CF.{phone}' = '8675309'"
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'should accept a hash with string values' do
|
260
|
+
Roart::Ticket.send(:construct_search_uri, {:custom_fields => {:phone => ['8675309', '5553265']}}).should == @query + "( 'CF.{phone}' = '8675309' OR 'CF.{phone}' = '5553265' )"
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
describe 'multiple find options' do
|
266
|
+
|
267
|
+
it 'should allow multiple find options' do
|
268
|
+
query = Roart::Ticket.send(:construct_search_uri, {:status => 'new', :queue => 'MyQueue'})
|
269
|
+
query.include?("Status = 'new'").should be_true
|
270
|
+
query.include?("Queue = 'MyQueue'").should be_true
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should search for :queue => 'A Queue', :status => [:new, :open]" do
|
274
|
+
query = Roart::Ticket.send(:construct_search_uri, {:queue => 'A Queue', :status => [:new, :open]})
|
275
|
+
query.include?("( Status = 'new' OR Status = 'open' )").should be_true
|
276
|
+
query.include?("Queue = 'A Queue'").should be_true
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
|
285
|
+
describe 'ticket methods' do
|
286
|
+
|
287
|
+
it 'should be able to load the full ticket' do
|
288
|
+
search_array = ['1:subject']
|
289
|
+
search_array.extend(Roart::TicketPage)
|
290
|
+
full_ticket = Roart::Ticket.send(:instantiate, {:id => 1, :subject => 'subject', :full => true})
|
291
|
+
ticket = Roart::Ticket.send(:instantiate, search_array.to_search_array ).first
|
292
|
+
Roart::Ticket.should_receive(:find).with(1).and_return(full_ticket)
|
293
|
+
ticket.load_full!
|
294
|
+
ticket.full.should be_true
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
data/spec/roart_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
dir = File.dirname(__FILE__)
|
3
|
+
|
4
|
+
$:.unshift(File.join(dir, '/../lib/'))
|
5
|
+
require dir + '/../lib/roart'
|
6
|
+
|
7
|
+
def dbtime(time)
|
8
|
+
time.strftime("%Y-%m-%d %H:%M:%S")
|
9
|
+
end
|
10
|
+
|
11
|
+
Spec::Runner.configure do |config|
|
12
|
+
# == Mock Framework
|
13
|
+
#
|
14
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
15
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
16
|
+
#
|
17
|
+
# config.mock_with :mocha
|
18
|
+
# config.mock_with :flexmock
|
19
|
+
# config.mock_with :rr
|
20
|
+
end
|
21
|
+
|
22
|
+
# EOF
|
data/test/test_roart.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pjdavis-roart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- PJ Davis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-14 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: mechanize
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bones
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.5.1
|
34
|
+
version:
|
35
|
+
description: Interface for working with Request Tracker (RT) tickets inspired by ActiveRecord.
|
36
|
+
email: pj.davis@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- History.txt
|
43
|
+
- README.rdoc
|
44
|
+
files:
|
45
|
+
- History.txt
|
46
|
+
- README.rdoc
|
47
|
+
- Rakefile
|
48
|
+
- lib/roart.rb
|
49
|
+
- lib/roart/connection.rb
|
50
|
+
- lib/roart/core/array.rb
|
51
|
+
- lib/roart/core/string.rb
|
52
|
+
- lib/roart/errors.rb
|
53
|
+
- lib/roart/roart.rb
|
54
|
+
- lib/roart/ticket.rb
|
55
|
+
- lib/roart/ticket_page.rb
|
56
|
+
- roart.gemspec
|
57
|
+
- spec/roart/connection_spec.rb
|
58
|
+
- spec/roart/core/array_spec.rb
|
59
|
+
- spec/roart/core/string_spec.rb
|
60
|
+
- spec/roart/roart_spec.rb
|
61
|
+
- spec/roart/ticket_page_spec.rb
|
62
|
+
- spec/roart/ticket_spec.rb
|
63
|
+
- spec/roart_spec.rb
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
- test/test_roart.rb
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/pjdavis/roart
|
68
|
+
licenses:
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options:
|
71
|
+
- --main
|
72
|
+
- README.rdoc
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
version:
|
87
|
+
requirements: []
|
88
|
+
|
89
|
+
rubyforge_project: roart
|
90
|
+
rubygems_version: 1.3.5
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: Interface for working with Request Tracker (RT) tickets inspired by ActiveRecord
|
94
|
+
test_files:
|
95
|
+
- test/test_roart.rb
|