ticketmaster-mingle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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