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 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
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  module Roart
3
3
 
4
4
  # :stopdoc:
5
- VERSION = '0.1.3'
5
+ VERSION = '0.1.4'
6
6
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
7
7
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
8
8
  # :startdoc:
@@ -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
- @attributes[:id] = create
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
- uri = "#{self.class.connection.server}/REST/1.0/ticket/#{self.id}/edit"
55
- payload = @attributes.clone
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
- raise "Ticket Create Failed"
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
- return tid[1].to_i
94
+ @attributes[:id] = tid[1].to_i
95
+ self.after_create
96
+ true
78
97
  else
79
- raise "Ticket Create Failed"
98
+ false
80
99
  end
81
100
  end
82
-
83
- class << self #class methods
84
101
 
85
- # Gives or Sets the connection object for the RT Server.
86
- # Accepts 3 parameters :server, :user, and :pass. Call this
87
- # at the top of your subclass to create the connection,
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
- add_queue!(query, options[:queues] || options[:queue])
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
@@ -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 create a ticket' do
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.3
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-18 00:00:00 -07:00
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