ticketmaster-mingle 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/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.8.7@ticketmaster-mingle
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "ticketmaster", "0.5.2"
4
+
5
+ group :development do
6
+ gem "bundler", "~> 1.0.0"
7
+ gem "jeweler", "~> 1.5.1"
8
+ gem "rcov", ">= 0"
9
+ gem "rspec", "= 1.2.9"
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.0.3)
5
+ activesupport (= 3.0.3)
6
+ builder (~> 2.1.2)
7
+ i18n (~> 0.4)
8
+ activeresource (3.0.3)
9
+ activemodel (= 3.0.3)
10
+ activesupport (= 3.0.3)
11
+ activesupport (3.0.3)
12
+ builder (2.1.2)
13
+ git (1.2.5)
14
+ hashie (0.3.0)
15
+ i18n (0.5.0)
16
+ jeweler (1.5.2)
17
+ bundler (~> 1.0.0)
18
+ git (>= 1.2.5)
19
+ rake
20
+ rake (0.8.7)
21
+ rcov (0.9.9)
22
+ rspec (1.2.9)
23
+ ticketmaster (0.5.2)
24
+ activeresource (>= 2.3.2)
25
+ activesupport (>= 2.3.2)
26
+ hashie (<= 0.3.0)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ bundler (~> 1.0.0)
33
+ jeweler (~> 1.5.1)
34
+ rcov
35
+ rspec (= 1.2.9)
36
+ ticketmaster (= 0.5.2)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 anymoto
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # ticketmaster-mingle
2
+
3
+ This is a provider for [ticketmaster](http://ticketrb.com). It provides interoperability with [Mingle](http://www.thoughtworks-studios.com/mingle-agile-project-management/) and it's issue tracking system through the ticketmaster gem.
4
+
5
+ # Usage and Examples
6
+
7
+ First we have to instantiate a new ticketmaster instance, your Mingle installation should have api access enable:
8
+ mingle = TicketMaster.new(:mingle, {:server => 'myserver', :username=> 'foo', :password => 'bar')
9
+ If you do not pass in the server name, username and password, you won't get any information.
10
+
11
+ Also you have to enable basic authentication, set the basic_authentication_enabled configuration option to true in the Mingle data directory/config/auth_config.yml file, where Mingle data directory is the path to the Mingle data directory:
12
+ basic_authentication_enabled: true
13
+
14
+ ## Finding Projects
15
+
16
+ You can find your own projects by doing:
17
+
18
+ projects = mingle.projects # Will return all your projects
19
+ projects = mingle.projects(["project1", "project2"]) # You must use your projects identifier
20
+ project = mingle.project("your_project") # Also use project identifier in here
21
+
22
+ ## Creating a project
23
+
24
+ project = mingle.project!(:name => "New Project", :identifier => "new_project", :description => "This is a new project")
25
+
26
+ ## Finding Tickets(Cards)
27
+
28
+ tickets = project.tickets # All tickets
29
+ ticket = project.ticket(<ticket_number>)
30
+
31
+ ## Open Tickets
32
+
33
+ ticket = project.ticket!({:name => "New ticket", :description=> "Body for the very new ticket"})
34
+
35
+
36
+ ## Finding comments
37
+
38
+ comments = project.ticket.comments
39
+
40
+ ## Creating a comment
41
+
42
+ comment = ticket.comment!(:content => 'New comment created.')
43
+
44
+ ## Requirements
45
+
46
+ * rubygems (obviously)
47
+ * ticketmaster gem (latest version preferred)
48
+ * jeweler gem (only if you want to repackage and develop)
49
+ * Mingle
50
+
51
+ The ticketmaster gem should automatically be installed during the installation of this gem if it is not already installed.
52
+
53
+ ## Other Notes
54
+
55
+ Since this and the ticketmaster gem is still primarily a work-in-progress, minor changes may be incompatible with previous versions. Please be careful about using and updating this gem in production.
56
+
57
+ If you see or find any issues, feel free to open up an issue report.
58
+
59
+
60
+ ## Note on Patches/Pull Requests
61
+
62
+ * Fork the project.
63
+ * Make your feature addition or bug fix.
64
+ * Add tests for it. This is important so we don't break it in a
65
+ future version unintentionally.
66
+ * Commit, do not mess with rakefile, version, or history.
67
+ (if you want to have your own version, that is fine but bump version in a commit by itself so we can ignore when I pull)
68
+ * Send us a pull request. Bonus points for topic branches.
69
+
70
+ ## Copyright
71
+
72
+ Copyright (c) 2010 The Hybrid Group. See LICENSE for details.
73
+
74
+
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "ticketmaster-mingle"
16
+ gem.homepage = "http://ticket.rb"
17
+ gem.summary = %Q{Ticketmaster Provider for Mingle}
18
+ gem.description = %Q{Allows ticketmaster to interact with Mingle}
19
+ gem.email = "ana@hybridgroup.com"
20
+ gem.authors = ["Hybridgroup"]
21
+ gem.add_dependency "activesupport", ">= 3.0.4"
22
+ gem.add_dependency "activeresource", ">= 3.0.4"
23
+ end
24
+ Jeweler::RubygemsDotOrgTasks.new
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :default => :spec
39
+
40
+ require 'rake/rdoctask'
41
+ Rake::RDocTask.new do |rdoc|
42
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "ticketmaster-mingle #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,228 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_resource'
4
+
5
+ # Ruby lib for working with the Mingle API's XML interface.
6
+ # You should set the authentication using your login
7
+ # credentials with HTTP Basic Authentication.
8
+
9
+ # This library is a small wrapper around the REST interface
10
+
11
+ module MingleAPI
12
+ class Error < StandardError; end
13
+ class << self
14
+
15
+ #Sets up basic authentication credentials for all the resources.
16
+ def authenticate(server, login, password)
17
+ @server = server
18
+ @username = login
19
+ @password = password
20
+ self::Base.user = login
21
+ self::Base.password = password
22
+
23
+ resources.each do |klass|
24
+ klass.site = klass.site_format % "http://#{login}:#{password}@#{server}/api/v2"
25
+ end
26
+ end
27
+
28
+ def resources
29
+ @resources ||= []
30
+ end
31
+ end
32
+
33
+ class Base < ActiveResource::Base
34
+ def self.inherited(base)
35
+ MingleAPI.resources << base
36
+ class << base
37
+ attr_accessor :site_format
38
+ end
39
+ base.site_format = '%s'
40
+ super
41
+ end
42
+ end
43
+
44
+ # Find projects
45
+ #
46
+ # MingleAPI::Project.find(:all) # find all projects for the current account.
47
+ # MingleAPI::Project.find('my_project') # find individual project by ID
48
+ #
49
+ # Creating a Project
50
+ #
51
+ # project = MingleAPI::Project.new(:name => 'Ninja Whammy Jammy')
52
+ # project.save
53
+ # # => true
54
+ #
55
+ #
56
+ # Updating a Project
57
+ #
58
+ # project = MingleAPI::Project.find('my_project')
59
+ # project.name = "A new name"
60
+ # project.save
61
+ #
62
+ # Finding tickets
63
+ #
64
+ # project = MingleAPI::Project.find('my_project')
65
+ # project.tickets
66
+ #
67
+
68
+
69
+ class Project < Base
70
+
71
+ #begin monkey patches
72
+
73
+ def exists?(id, options = {})
74
+ begin
75
+ self.class.find(id)
76
+ true
77
+ rescue ActiveResource::ResourceNotFound, ActiveResource::ResourceGone
78
+ false
79
+ end
80
+ end
81
+
82
+ def new?
83
+ !self.exists?(id)
84
+ end
85
+
86
+ def element_path(options = nil)
87
+ self.class.element_path(self.id, options)
88
+ end
89
+
90
+ def encode(options={})
91
+ val = []
92
+ attributes.each_pair do |key, value|
93
+ val << "project[#{URI.escape key}]=#{URI.escape value}" rescue nil
94
+ end
95
+ val.join('&')
96
+ end
97
+
98
+ def create
99
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
100
+ self.id = id_from_response(response)
101
+ load_attributes_from_response(response)
102
+ end
103
+ end
104
+
105
+ #end monkey patches
106
+
107
+ def tickets(options = {})
108
+ Card.find(:all, :params => options.update(:identifier => id))
109
+ end
110
+
111
+ def id
112
+ @attributes['identifier']
113
+ end
114
+
115
+ end
116
+
117
+ # Find tickets
118
+ #
119
+ # MingleAPI::Ticket.find(:all, :params => { :identifier => 'my_project' })
120
+ #
121
+ # project = UnfuddleAPI::Project.find('my_project')
122
+ # project.tickets
123
+ # project.tickets(:name => 'a new name')
124
+ #
125
+
126
+
127
+ class Card < Base
128
+ self.site_format << '/projects/:identifier/'
129
+
130
+ #begin monkey patches
131
+
132
+ def element_path(options = nil)
133
+ self.class.element_path(self.number, options)
134
+ end
135
+
136
+ def encode(options={})
137
+ val = []
138
+ attributes.each_pair do |key, value|
139
+ unless value.nil?
140
+ case key
141
+ when 'card_type'
142
+ if value.is_a? Hash
143
+ name = value[:name]
144
+ else
145
+ name = value.name
146
+ end
147
+ val << "card[card_type_name]=#{URI.escape name}"
148
+ when 'properties'
149
+ value.each {|property|
150
+ val << "card[properties][][name]=#{URI.escape property[0]}
151
+ &card[properties][][value]=#{URI.escape property[1]}"} rescue NoMethodError
152
+ else
153
+ val << "card[#{URI.escape key.to_s}]=#{URI.escape value.to_s}" rescue nil
154
+ end
155
+ end
156
+ end
157
+ val.join('&')
158
+ end
159
+
160
+ def update
161
+ connection.put(element_path(prefix_options) + '?' + encode, nil, self.class.headers).tap do |response|
162
+ load_attributes_from_response(response)
163
+ end
164
+ end
165
+
166
+ def create
167
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
168
+ self.number = id_from_response(response)
169
+ load_attributes_from_response(response)
170
+ end
171
+ end
172
+
173
+ #end monkey patches
174
+
175
+ def number
176
+ @attributes['number']
177
+ end
178
+
179
+ def id
180
+ @attributes['id']
181
+ end
182
+
183
+ def name
184
+ @attributes['name']
185
+ end
186
+
187
+ def created_on
188
+ @attributes['created_on']
189
+ end
190
+
191
+ def modified_on
192
+ @attributes['modified_on']
193
+ end
194
+
195
+ def description
196
+ @attributes['description']
197
+ end
198
+
199
+ def card_type
200
+ @attributes['card_type']
201
+ end
202
+
203
+ def properties
204
+ @attributes['properties']
205
+ end
206
+
207
+ end
208
+
209
+ class Comment < Base
210
+ self.site_format << '/projects/:identifier/cards/:number'
211
+
212
+ def create
213
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
214
+ load_attributes_from_response(response)
215
+ end
216
+ end
217
+
218
+ def encode(options={})
219
+ val=[]
220
+ attributes.each_pair do |key, value|
221
+ val << "comment[#{URI.escape key}]=#{URI.escape value}" rescue nil
222
+ end
223
+ val.join('&')
224
+ end
225
+
226
+ end
227
+
228
+ end
@@ -0,0 +1,47 @@
1
+ module TicketMaster::Provider
2
+ module Mingle
3
+ # The comment class for ticketmaster-mingle
4
+ #
5
+ # Do any mapping between Ticketmaster and your system's comment model here
6
+ # versions of the ticket.
7
+ #
8
+ class Comment < TicketMaster::Provider::Base::Comment
9
+ API = MingleAPI::Comment # The class to access the api's comments
10
+ # declare needed overloaded methods here
11
+
12
+ def initialize(*object)
13
+ if object.first
14
+ object = object.first
15
+ @system_data = {:client => object}
16
+ unless object.is_a? Hash
17
+ hash = {:content => object.content,
18
+ :created_at => object.created_at,
19
+ :created_by => object.created_by,
20
+ :ticket_id => object.prefix_options[:number],
21
+ :project_id => object.prefix_options[:identifier]}
22
+ else
23
+ hash = object
24
+ end
25
+ super hash
26
+ end
27
+ end
28
+
29
+ def created_by
30
+ self[:created_by]
31
+ end
32
+
33
+ def created_at
34
+ self[:created_at]
35
+ end
36
+
37
+ def project_id
38
+ self[:identifier]
39
+ end
40
+
41
+ def ticket_id
42
+ self[:number]
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,29 @@
1
+ module TicketMaster::Provider
2
+ # This is the Mingle Provider for ticketmaster
3
+ module Mingle
4
+ include TicketMaster::Provider::Base
5
+ TICKET_API = MingleAPI::Card # The class to access the api's cards
6
+ PROJECT_API = MingleAPI::Project # The class to access the api's projects
7
+
8
+ # This is for cases when you want to instantiate using TicketMaster::Provider::Mingle.new(auth)
9
+ def self.new(auth = {})
10
+ TicketMaster.new(:mingle, auth)
11
+ end
12
+
13
+ # Providers must define an authorize method. This is used to initialize and set authentication
14
+ # parameters to access the API
15
+
16
+ def authorize(auth = {})
17
+ @authentication ||= TicketMaster::Authenticator.new(auth)
18
+ auth = @authentication
19
+ if auth.server.blank? and auth.login.blank? and auth.password.blank?
20
+ raise "Please provide server, login and password"
21
+ end
22
+ MingleAPI.authenticate(auth.server, auth.login, auth.password)
23
+ end
24
+ # declare needed overloaded methods here
25
+
26
+ end
27
+ end
28
+
29
+
@@ -0,0 +1,53 @@
1
+ module TicketMaster::Provider
2
+ module Mingle
3
+ # Project class for ticketmaster-mingle
4
+ #
5
+ #
6
+ class Project < TicketMaster::Provider::Base::Project
7
+ API = MingleAPI::Project # The class to access the api's projects
8
+ # declare needed overloaded methods here
9
+
10
+ def id
11
+ self[:identifier]
12
+ end
13
+
14
+ def initialize(*options)
15
+ super(*options)
16
+ end
17
+
18
+ def tickets(*options)
19
+ begin
20
+ if options.first.is_a? Hash
21
+ #options[0].merge!(:params => {:id => id})
22
+ super(*options)
23
+ elsif options.empty?
24
+ tickets = MingleAPI::Card.find(:all, :params => {:identifier => id}).collect { |ticket| TicketMaster::Provider::Mingle::Ticket.new ticket }
25
+ else
26
+ super(*options)
27
+ end
28
+ rescue
29
+ []
30
+ end
31
+ end
32
+
33
+ def ticket!(*options)
34
+ options[0].merge!(:identifier => id) if options.first.is_a?(Hash)
35
+ provider_parent(self.class)::Ticket.create(*options)
36
+ end
37
+
38
+ # copy from this.copy(that) copies that into this
39
+ def copy(project)
40
+ project.tickets.each do |ticket|
41
+ copy_ticket = self.ticket!(:name => ticket.title, :description => ticket.description)
42
+ ticket.comments.each do |comment|
43
+ copy_ticket.comment!(:content => comment.body)
44
+ sleep 1
45
+ end
46
+ end
47
+ end
48
+
49
+ end
50
+ end
51
+ end
52
+
53
+
@@ -0,0 +1,102 @@
1
+ module TicketMaster::Provider
2
+ module Mingle
3
+ # Ticket class for ticketmaster-mingle
4
+ #
5
+ API = MingleAPI::Card
6
+
7
+ class Ticket < TicketMaster::Provider::Base::Ticket
8
+ # declare needed overloaded methods herea
9
+
10
+ def initialize(*object)
11
+ if object.first
12
+ args = object
13
+ object = args.shift
14
+ identifier = args.shift
15
+ @system_data = {:client => object}
16
+ unless object.is_a? Hash
17
+ hash = {:number => object.number,
18
+ :name => object.name,
19
+ :description => object.description,
20
+ :card_type_name => object.card_type.nil? ? "Card" : object.card_type.name,
21
+ :identifier => identifier,
22
+ :created_on => object.created_on,
23
+ :modified_on => object.modified_on,
24
+ :properties => object.properties}
25
+ else
26
+ hash = object
27
+ end
28
+ super hash
29
+ end
30
+ end
31
+
32
+ def self.create(*options)
33
+ card = API.new(*options)
34
+ ticket = self.new card
35
+ card.save
36
+ ticket
37
+ end
38
+
39
+ def self.find_by_id(identifier, number)
40
+ self.search(identifier, {'number' => number}).first
41
+ end
42
+
43
+ def self.search(identifier, options = {}, limit = 1000)
44
+ tickets = API.find(:all, :params => {:identifier => identifier}).collect { |ticket| self.new ticket, identifier }
45
+ search_by_attribute(tickets, options, limit)
46
+ end
47
+
48
+ def self.find_by_attributes(identifier, attributes = {})
49
+ self.search(identifier, attributes)
50
+ end
51
+
52
+ def number
53
+ self[:number].to_i
54
+ end
55
+
56
+ def id
57
+ self[:id].to_i
58
+ end
59
+
60
+ def name
61
+ self[:name]
62
+ end
63
+
64
+ def identifier
65
+ self[:identifier]
66
+ end
67
+
68
+ def title
69
+ self[:name]
70
+ end
71
+
72
+ def description
73
+ self[:description]
74
+ end
75
+
76
+ def status
77
+ self.properties[1].value
78
+ end
79
+
80
+ def comments(*options)
81
+ begin
82
+ if options.empty?
83
+ comments = MingleAPI::Comment.find(:all, :params => {:identifier => identifier, :number => number}).collect { |comment| TicketMaster::Provider::Mingle::Comment.new comment }
84
+ else
85
+ super(*options)
86
+ end
87
+ rescue
88
+ []
89
+ end
90
+ end
91
+
92
+ #def comment(*options)
93
+
94
+ def comment!(*options)
95
+ options[0].update(:identifier => identifier, :number => number) if options.first.is_a?(Hash)
96
+ Comment.create(*options)
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/mingle/mingle-api'
2
+
3
+ %w{ mingle ticket project comment }.each do |f|
4
+ require File.dirname(__FILE__) + '/provider/' + f + '.rb';
5
+ end