pjdavis-roart 0.1.3 → 0.1.4
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 +6 -0
- data/README.rdoc +14 -0
- data/lib/roart.rb +1 -1
- data/lib/roart/callbacks.rb +25 -0
- data/lib/roart/ticket.rb +83 -35
- data/roart.gemspec +37 -0
- data/spec/roart/callbacks_spec.rb +49 -0
- data/spec/roart/ticket_spec.rb +30 -7
- data/spec/spec_helper.rb +5 -0
- metadata +5 -2
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
==0.1.4 / 2009-08-19
|
2
|
+
Implemented callbacks, you can now hook into the ticket life-cycle with before and after create and update.
|
3
|
+
Saving works like ActiveRecord now, with save returning true if successful and false otherwise, and save! raising an error if unsuccessful.
|
4
|
+
Creating tickets is more ActiveRecord like now, with new not saving to the ticketing system automatically, you must call save or save!. There is a create function to do this now. Although this does break backward compatability, I'm not going to bump the minor because a) nobody has forked this yet, and b) i skipped 0.
|
5
|
+
You can now specify a default queue when you subclass Roart::Ticket. just add a default_queue 'queue name' to your class and that queue will automatically be searched unless you specify a queue.
|
6
|
+
|
1
7
|
==0.1.3 / 2009-08-18
|
2
8
|
Can now update tickets with #save. Returns true if saved, raises an error if not.
|
3
9
|
|
data/README.rdoc
CHANGED
@@ -49,6 +49,20 @@ If you are using Best Practical's Request Tracker (RT) and you need to interact
|
|
49
49
|
|
50
50
|
my_ticket.histories #-> Returns an array of history objects
|
51
51
|
|
52
|
+
* Create a new ticket
|
53
|
+
|
54
|
+
issue = Ticket.new(:queue => 'some_queue', :subject => 'This is not working for me')
|
55
|
+
issue.id #-> 'ticket/new'
|
56
|
+
issue.save
|
57
|
+
issue.id #-> 23423
|
58
|
+
|
59
|
+
* Update a ticket
|
60
|
+
|
61
|
+
ticket = Ticket.find(23452)
|
62
|
+
ticket.subject #-> "Some Subject for a ticket."
|
63
|
+
ticket.subject #-> "Smoke me a kipper, I'll be back for breakfast."
|
64
|
+
ticket.save
|
65
|
+
ticket.subject #->"Smoke me a kipper, I'll be back for breakfast."
|
52
66
|
|
53
67
|
|
54
68
|
== REQUIREMENTS:
|
data/lib/roart.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Roart
|
2
|
+
|
3
|
+
# Callbacks are implemented to do a bit of logic either before or after a part of the object life cycle. These can be overridden in your Ticket class and will be called at the approprate times.
|
4
|
+
#
|
5
|
+
module Callbacks
|
6
|
+
|
7
|
+
# called just before a ticket that has not been saved to the ticketing system is saved.
|
8
|
+
#
|
9
|
+
def before_create; end
|
10
|
+
|
11
|
+
# Called immediately a ticket that has not been saved is saved.
|
12
|
+
#
|
13
|
+
def before_update; end
|
14
|
+
|
15
|
+
# called just before a ticket that has been updated is saved to the ticketing system
|
16
|
+
#
|
17
|
+
def after_create; end
|
18
|
+
|
19
|
+
# called just after a ticket that has been updated is saved to the ticketing system
|
20
|
+
#
|
21
|
+
def after_update; end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/roart/ticket.rb
CHANGED
@@ -10,8 +10,9 @@ module Roart
|
|
10
10
|
class Ticket
|
11
11
|
|
12
12
|
include Roart::MethodFunctions
|
13
|
+
include Roart::Callbacks
|
13
14
|
|
14
|
-
attr_reader :full, :history
|
15
|
+
attr_reader :full, :history, :saved
|
15
16
|
|
16
17
|
# Creates a new ticket. Attributes queue and subject are required. Expects a hash with the attributes of the ticket.
|
17
18
|
#
|
@@ -23,7 +24,7 @@ module Roart
|
|
23
24
|
if attributes.is_a?(Hash)
|
24
25
|
@attributes = Roart::Tickets::DefaultAttributes.to_hash.merge(attributes)
|
25
26
|
@attributes.update(:id => 'ticket/new')
|
26
|
-
@
|
27
|
+
@saved = false
|
27
28
|
else
|
28
29
|
raise ArgumentError, "Expects a hash."
|
29
30
|
end
|
@@ -34,7 +35,7 @@ module Roart
|
|
34
35
|
# Loads all information for a ticket from RT and lets full to true.
|
35
36
|
# This changes the ticket object and adds methods for all the fields on the ticket.
|
36
37
|
# Custom fields will be prefixed with 'cf' so a custom field of 'phone'
|
37
|
-
# would be cf_phone
|
38
|
+
# would be cf_phone. custom fields hold their case from how they are defined in RT, so a custom field of PhoneNumber would be cf_PhoneNumber and a custom field of phone_number would be cf_phone_number
|
38
39
|
#
|
39
40
|
def load_full!
|
40
41
|
unless self.full
|
@@ -50,52 +51,60 @@ module Roart
|
|
50
51
|
@histories ||= Roart::History.default(:ticket => self)
|
51
52
|
end
|
52
53
|
|
54
|
+
# if a ticket is new, calling save will create it in the ticketing system and assign the id that it gets to the id attribute. It returns true if the save was successful, and false if something went wrong
|
55
|
+
#
|
53
56
|
def save
|
54
|
-
|
55
|
-
|
56
|
-
payload.delete(:id)
|
57
|
-
payload = payload.to_content_format
|
58
|
-
resp = self.class.connection.post(uri, :content => payload)
|
59
|
-
resp = resp.split("\n")
|
60
|
-
raise "Ticket Update Failed" unless resp.first.include?("200")
|
61
|
-
if resp[2].match(/^# Ticket (\d+) updated./)
|
62
|
-
return true
|
57
|
+
if self.id == "ticket/new"
|
58
|
+
self.create
|
63
59
|
else
|
64
|
-
|
60
|
+
self.before_update
|
61
|
+
uri = "#{self.class.connection.server}/REST/1.0/ticket/#{self.id}/edit"
|
62
|
+
payload = @attributes.clone
|
63
|
+
payload.delete(:id)
|
64
|
+
payload = payload.to_content_format
|
65
|
+
resp = self.class.connection.post(uri, :content => payload)
|
66
|
+
resp = resp.split("\n")
|
67
|
+
raise "Ticket Update Failed" unless resp.first.include?("200")
|
68
|
+
if resp[2].match(/^# Ticket (\d+) updated./)
|
69
|
+
self.after_update
|
70
|
+
true
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
65
74
|
end
|
66
75
|
end
|
67
76
|
|
77
|
+
# works just like save, but if the save fails, it raises an exception instead of silently returning false
|
78
|
+
#
|
79
|
+
def save!
|
80
|
+
raise "Ticket Create Failed" unless self.save
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
68
84
|
protected
|
69
85
|
|
70
|
-
def create
|
86
|
+
def create #:nodoc:
|
87
|
+
self.before_create
|
71
88
|
uri = "#{self.class.connection.server}/REST/1.0/ticket/new"
|
72
89
|
payload = @attributes.to_content_format
|
73
90
|
resp = self.class.connection.post(uri, :content => payload)
|
74
91
|
resp = resp.split("\n")
|
75
92
|
raise "Ticket Create Failed" unless resp.first.include?("200")
|
76
93
|
if tid = resp[2].match(/^# Ticket (\d+) created./)
|
77
|
-
|
94
|
+
@attributes[:id] = tid[1].to_i
|
95
|
+
self.after_create
|
96
|
+
true
|
78
97
|
else
|
79
|
-
|
98
|
+
false
|
80
99
|
end
|
81
100
|
end
|
82
|
-
|
83
|
-
class << self #class methods
|
84
101
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
# class Ticket < Roart::Ticket
|
89
|
-
# connection :server => 'server', :user => 'user', :pass => 'pass'
|
90
|
-
# end
|
91
|
-
#
|
92
|
-
def connection(options=nil)
|
93
|
-
if options && @connection.nil?
|
94
|
-
@connection = Roart::Connection.new(options)
|
95
|
-
else
|
96
|
-
@connection
|
97
|
-
end
|
102
|
+
def create! #:nodoc:
|
103
|
+
raise "Ticket Create Failed" unless self.create
|
104
|
+
true
|
98
105
|
end
|
106
|
+
|
107
|
+
class << self #class methods
|
99
108
|
|
100
109
|
# Searches for a ticket or group of tickets with an active record like interface.
|
101
110
|
#
|
@@ -140,6 +149,41 @@ module Roart
|
|
140
149
|
end
|
141
150
|
end
|
142
151
|
|
152
|
+
|
153
|
+
# Gives or Sets the connection object for the RT Server.
|
154
|
+
# Accepts 3 parameters :server, :user, and :pass. Call this
|
155
|
+
# at the top of your subclass to create the connection,
|
156
|
+
# class Ticket < Roart::Ticket
|
157
|
+
# connection :server => 'server', :user => 'user', :pass => 'pass'
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
def connection(options=nil)
|
161
|
+
if options
|
162
|
+
@connection = Roart::Connection.new(options)
|
163
|
+
else
|
164
|
+
defined?(@connection) ? @connection : nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Adds a default queue to search each time. This is overridden by
|
169
|
+
# specifically including a :queue option in your find method. This can
|
170
|
+
# be an array of queue names or a string with a single queue name.
|
171
|
+
#
|
172
|
+
def default_queue(options=nil)
|
173
|
+
if options
|
174
|
+
@default_queue = options
|
175
|
+
else
|
176
|
+
defined?(@default_queue) ? @default_queue : nil
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# creates a new ticket object and immediately saves it to the database.
|
181
|
+
def create(options)
|
182
|
+
ticket = self.new(options)
|
183
|
+
ticket.save
|
184
|
+
ticket
|
185
|
+
end
|
186
|
+
|
143
187
|
protected
|
144
188
|
|
145
189
|
def instantiate(attrs) #:nodoc:
|
@@ -211,14 +255,18 @@ module Roart
|
|
211
255
|
get_ticket_from_uri(uri)
|
212
256
|
end
|
213
257
|
|
214
|
-
def construct_search_uri(options) #:nodoc:
|
258
|
+
def construct_search_uri(options={}) #:nodoc:
|
215
259
|
uri = "#{self.connection.server}/REST/1.0/search/ticket?"
|
216
260
|
uri << 'orderby=-Created&' if options.delete(:order)
|
217
|
-
unless options.empty?
|
261
|
+
unless options.empty? && default_queue.nil?
|
218
262
|
uri << 'query= '
|
219
263
|
query = Array.new
|
220
|
-
|
221
|
-
|
264
|
+
|
265
|
+
if options[:queues] || options[:queue]
|
266
|
+
add_queue!(query, options[:queues] || options[:queue])
|
267
|
+
else
|
268
|
+
add_queue!(query, default_queue)
|
269
|
+
end
|
222
270
|
add_dates!(query, options)
|
223
271
|
add_searches!(query, options)
|
224
272
|
add_status!(query, options[:status])
|
data/roart.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{roart}
|
5
|
+
s.version = "0.1.4"
|
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-19}
|
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", "spec/test_data/full_history.txt", "spec/test_data/single_history.txt"]
|
13
|
+
s.files = ["History.txt", "README.rdoc", "Rakefile", "lib/roart.rb", "lib/roart/callbacks.rb", "lib/roart/connection.rb", "lib/roart/core/array.rb", "lib/roart/core/hash.rb", "lib/roart/core/string.rb", "lib/roart/errors.rb", "lib/roart/history.rb", "lib/roart/roart.rb", "lib/roart/ticket.rb", "lib/roart/ticket_page.rb", "roart.gemspec", "spec/roart/callbacks_spec.rb", "spec/roart/connection_spec.rb", "spec/roart/core/array_spec.rb", "spec/roart/core/hash_spec.rb", "spec/roart/core/string_spec.rb", "spec/roart/history_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", "spec/test_data/full_history.txt", "spec/test_data/single_history.txt"]
|
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
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_runtime_dependency(%q<mechanize>, [">= 0.9.0"])
|
28
|
+
s.add_development_dependency(%q<bones>, [">= 2.5.1"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<mechanize>, [">= 0.9.0"])
|
31
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<mechanize>, [">= 0.9.0"])
|
35
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[ .. spec_helper])
|
2
|
+
|
3
|
+
describe 'ticket callbacks' do
|
4
|
+
|
5
|
+
describe 'create callbacks' do
|
6
|
+
|
7
|
+
before do
|
8
|
+
post_data = @payload = {:subject => 'A New Ticket', :queue => 'My Queue'}
|
9
|
+
post_data.update(:id => 'ticket/new')
|
10
|
+
post_data = to_content_format(post_data)
|
11
|
+
mock_connection = mock('connection')
|
12
|
+
mock_connection.should_receive(:post).with('uri/REST/1.0/ticket/new', {:content => post_data}).and_return("RT/3.6.6 200 Ok\n\n# Ticket 267783 created.")
|
13
|
+
mock_connection.should_receive(:server).and_return('uri')
|
14
|
+
Roart::Ticket.should_receive(:connection).twice.and_return(mock_connection)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should call before_create callback' do
|
18
|
+
|
19
|
+
ticket = Roart::Ticket.new(@payload)
|
20
|
+
ticket.should_receive(:before_create)
|
21
|
+
ticket.should_receive(:after_create)
|
22
|
+
ticket.save
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'update callbacks' do
|
28
|
+
|
29
|
+
before do
|
30
|
+
@post_data = @payload = {:subject => 'A New Ticket', :queue => 'My Queue'}
|
31
|
+
@post_data[:subject] = 'An Old Ticket'
|
32
|
+
@post_data = to_content_format(@post_data)
|
33
|
+
@mock_connection = mock('connection')
|
34
|
+
@mock_connection.should_receive(:server).and_return('uri')
|
35
|
+
Roart::Ticket.should_receive(:connection).twice.and_return(@mock_connection)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should call before_update callbacks' do
|
39
|
+
@mock_connection.should_receive(:post).with('uri/REST/1.0/ticket/1/edit', {:content => @post_data}).and_return("RT/3.6.6 200 Ok\n\n# Ticket 267783 updated.")
|
40
|
+
ticket = Roart::Ticket.send(:instantiate, @payload.update(:id => 1))
|
41
|
+
ticket.instance_variable_set("@saved", false)
|
42
|
+
ticket.should_receive(:before_update)
|
43
|
+
ticket.should_receive(:after_update)
|
44
|
+
ticket.save
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/spec/roart/ticket_spec.rb
CHANGED
@@ -143,7 +143,7 @@ describe "Ticket" do
|
|
143
143
|
it 'should take multiple queues' do
|
144
144
|
Roart::Ticket.send(:construct_search_uri, {:queue => ['myQueue', 'another']}).should == @query + "( Queue = 'myQueue' OR Queue = 'another' )"
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
end
|
148
148
|
|
149
149
|
describe 'dates' do
|
@@ -282,6 +282,28 @@ describe "Ticket" do
|
|
282
282
|
|
283
283
|
end
|
284
284
|
|
285
|
+
describe "the default queue" do
|
286
|
+
|
287
|
+
before do
|
288
|
+
@connection = mock('connection', :server => "server")
|
289
|
+
@search_string = "/REST/1.0/search/ticket?"
|
290
|
+
@query = @connection.server + @search_string + 'query= '
|
291
|
+
class MyTicket < Roart::Ticket; end
|
292
|
+
MyTicket.instance_variable_set("@default_queue", 'myQueue')
|
293
|
+
MyTicket.should_receive(:connection).and_return(@connection)
|
294
|
+
end
|
295
|
+
|
296
|
+
|
297
|
+
it 'should have a default queue' do
|
298
|
+
MyTicket.send(:construct_search_uri, :status => :new).should == @query + "Queue = 'myQueue' AND Status = 'new'"
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'should search without options and return the default queue' do
|
302
|
+
MyTicket.send(:construct_search_uri).should == @query + "Queue = 'myQueue'"
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|
306
|
+
|
285
307
|
describe 'ticket methods' do
|
286
308
|
|
287
309
|
|
@@ -305,11 +327,6 @@ describe "Ticket" do
|
|
305
327
|
|
306
328
|
describe 'manipulating tickets' do
|
307
329
|
|
308
|
-
def to_content_format(data)
|
309
|
-
fields = data.map { |key,value| "#{key.to_s.camelize}: #{value}" unless value.nil? }
|
310
|
-
fields.compact.join("\n")
|
311
|
-
end
|
312
|
-
|
313
330
|
describe 'creating tickets' do
|
314
331
|
|
315
332
|
before do
|
@@ -322,13 +339,19 @@ describe "Ticket" do
|
|
322
339
|
Roart::Ticket.should_receive(:connection).twice.and_return(mock_connection)
|
323
340
|
end
|
324
341
|
|
325
|
-
it 'should be able to
|
342
|
+
it 'should be able to save a new ticket' do
|
326
343
|
ticket = Roart::Ticket.new(@payload)
|
344
|
+
ticket.save
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'should be able to create a ticket' do
|
348
|
+
ticket = Roart::Ticket.create(@payload)
|
327
349
|
end
|
328
350
|
|
329
351
|
it 'should return a newly created ticket' do
|
330
352
|
ticket = Roart::Ticket.new(@payload)
|
331
353
|
ticket.class.should == Roart::Ticket
|
354
|
+
ticket.save
|
332
355
|
ticket.id.should == 267783
|
333
356
|
end
|
334
357
|
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,11 @@ def dbtime(time)
|
|
8
8
|
time.strftime("%Y-%m-%d %H:%M:%S")
|
9
9
|
end
|
10
10
|
|
11
|
+
def to_content_format(data)
|
12
|
+
fields = data.map { |key,value| "#{key.to_s.camelize}: #{value}" unless value.nil? }
|
13
|
+
fields.compact.join("\n")
|
14
|
+
end
|
15
|
+
|
11
16
|
Spec::Runner.configure do |config|
|
12
17
|
# == Mock Framework
|
13
18
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pjdavis-roart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PJ Davis
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-19 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- README.rdoc
|
49
49
|
- Rakefile
|
50
50
|
- lib/roart.rb
|
51
|
+
- lib/roart/callbacks.rb
|
51
52
|
- lib/roart/connection.rb
|
52
53
|
- lib/roart/core/array.rb
|
53
54
|
- lib/roart/core/hash.rb
|
@@ -57,6 +58,8 @@ files:
|
|
57
58
|
- lib/roart/roart.rb
|
58
59
|
- lib/roart/ticket.rb
|
59
60
|
- lib/roart/ticket_page.rb
|
61
|
+
- roart.gemspec
|
62
|
+
- spec/roart/callbacks_spec.rb
|
60
63
|
- spec/roart/connection_spec.rb
|
61
64
|
- spec/roart/core/array_spec.rb
|
62
65
|
- spec/roart/core/hash_spec.rb
|