mingle4r 0.3.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 +40 -0
- data/MIT-LICENSE +21 -0
- data/README +227 -0
- data/TODO.txt +7 -0
- data/lib/mingle4r/api/v1/card/attachment.rb +51 -0
- data/lib/mingle4r/api/v1/card.rb +173 -0
- data/lib/mingle4r/api/v1/project.rb +71 -0
- data/lib/mingle4r/api/v1/property_definition.rb +16 -0
- data/lib/mingle4r/api/v1/transition_execution.rb +15 -0
- data/lib/mingle4r/api/v1/user.rb +9 -0
- data/lib/mingle4r/api/v1/wiki.rb +12 -0
- data/lib/mingle4r/api/v1.rb +25 -0
- data/lib/mingle4r/api/v2/card/attachment.rb +51 -0
- data/lib/mingle4r/api/v2/card/comment.rb +16 -0
- data/lib/mingle4r/api/v2/card/transition.rb +52 -0
- data/lib/mingle4r/api/v2/card.rb +157 -0
- data/lib/mingle4r/api/v2/murmur.rb +14 -0
- data/lib/mingle4r/api/v2/project.rb +90 -0
- data/lib/mingle4r/api/v2/property_definition.rb +14 -0
- data/lib/mingle4r/api/v2/user.rb +9 -0
- data/lib/mingle4r/api/v2/wiki.rb +12 -0
- data/lib/mingle4r/api/v2.rb +25 -0
- data/lib/mingle4r/api.rb +31 -0
- data/lib/mingle4r/common_class_methods.rb +220 -0
- data/lib/mingle4r/common_dyn_class_instance_methods.rb +5 -0
- data/lib/mingle4r/helpers.rb +33 -0
- data/lib/mingle4r/mingle_client.rb +91 -0
- data/lib/mingle4r/version.rb +11 -0
- data/lib/mingle4r.rb +41 -0
- data/lib/mingle_resource.rb +2 -0
- metadata +93 -0
@@ -0,0 +1,220 @@
|
|
1
|
+
module Mingle4r
|
2
|
+
# ActiveResource makes connecting to rest resources very easy. However it has one problem
|
3
|
+
# and a big one at that. If you try setting the authentication credentials or the site or
|
4
|
+
# collection name, element name for the class for the second time it doesn't work. E.g.
|
5
|
+
#
|
6
|
+
# class Person < ActiveResource::base
|
7
|
+
# self.site = 'http://localhost:9090/'
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# After sometime you change it to
|
11
|
+
#
|
12
|
+
# Person.site = 'https://org-server/my_proj/'
|
13
|
+
# Person.user = 'admin'
|
14
|
+
# Person.password = 'secret'
|
15
|
+
#
|
16
|
+
# Then you do
|
17
|
+
#
|
18
|
+
# Person.find(:all) => It bombs
|
19
|
+
#
|
20
|
+
# This module provides a mechanism by which you can get rid of this problem. Extend this
|
21
|
+
# class in the actual class itself. Do not extend the extended class from ActiveResource::Base.
|
22
|
+
#
|
23
|
+
# E.g.
|
24
|
+
#
|
25
|
+
# class Person
|
26
|
+
# extend CommonClassMethods
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# set the credentials
|
30
|
+
#
|
31
|
+
# Person.site = 'http://localhost:8080'
|
32
|
+
# Person.user = 'foo'
|
33
|
+
# Person.password = 'bar'
|
34
|
+
#
|
35
|
+
# Thats it. Now create some objects
|
36
|
+
#
|
37
|
+
# asur = Person.new(:name => 'Asur', :job => 'fooling around', :status => 'Single and ready 2 mingle')
|
38
|
+
# asur.save
|
39
|
+
#
|
40
|
+
# Now change the class attributes
|
41
|
+
#
|
42
|
+
# Person.site = 'https://org-server/mingle'
|
43
|
+
# Person.collection_name = 'boring_people'
|
44
|
+
#
|
45
|
+
# Now instantiate an object
|
46
|
+
#
|
47
|
+
# rakhshas = Person.new(:name => 'Rakhshas', :job => 'eating people', :status => 'just woke up and hungry')
|
48
|
+
# rakhshas.save => Voila !!!!!!! it works
|
49
|
+
#
|
50
|
+
# CUSTOMIZATIONS
|
51
|
+
# --------------
|
52
|
+
#
|
53
|
+
# No amount of wrapping can provide very detailed customizations. Either you have a lot of methods
|
54
|
+
# that are not being used or there is hardly anything at all. To oversome this problem this module
|
55
|
+
# was written to provide only those methods which are common to most active resource objects.
|
56
|
+
# However if you want to have a little more control over your active resource objects its very easy.
|
57
|
+
# Here's how you would do it normally
|
58
|
+
#
|
59
|
+
# class Person < ActiveResource::Base
|
60
|
+
# def self.count
|
61
|
+
# find(:all).size
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# def occupation
|
65
|
+
# return job if job
|
66
|
+
# 'Unemployed'
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# To do the same thing, here's how you do it using this library
|
71
|
+
#
|
72
|
+
# class Person
|
73
|
+
# module ClassMethods
|
74
|
+
# def count
|
75
|
+
# find(:all).size
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# module InstanceMethods
|
80
|
+
# def occupation
|
81
|
+
# return job if job
|
82
|
+
# 'Unemployed'
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
# extend CommonClassMethods
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# The instance methods will be available as instance methods in the objects created, class methods
|
89
|
+
# will be available as class methods in the class of the object.
|
90
|
+
|
91
|
+
module CommonClassMethods
|
92
|
+
attr_reader :site, :user, :password
|
93
|
+
|
94
|
+
# creates an object of the class in which this module is extended
|
95
|
+
def new(args = {})
|
96
|
+
# @resource_class ||= create_resource_class() # should this be commented
|
97
|
+
@resource_class.new(args)
|
98
|
+
end
|
99
|
+
|
100
|
+
# sets the site for the class in which this module is extended
|
101
|
+
def site=(site)
|
102
|
+
if site != self.site
|
103
|
+
@site = site
|
104
|
+
uri = URI.parse(site)
|
105
|
+
@user = URI.decode(uri.user) if(uri.user)
|
106
|
+
@password = URI.decode(uri.password) if(uri.password)
|
107
|
+
@resource_class = self.send(:create_resource_class)
|
108
|
+
end
|
109
|
+
@site
|
110
|
+
end
|
111
|
+
|
112
|
+
# sets the user for the class in which this module is extended
|
113
|
+
def user=(user)
|
114
|
+
if user != self.user
|
115
|
+
@user = user
|
116
|
+
@resource_class = self.send(:create_resource_class) if(site)
|
117
|
+
end
|
118
|
+
@user
|
119
|
+
end
|
120
|
+
|
121
|
+
# sets the password for the class in which this module is extended
|
122
|
+
def password=(password)
|
123
|
+
if password != self.password
|
124
|
+
@password = password
|
125
|
+
@resource_class = self.send(:create_resource_class) if(site)
|
126
|
+
end
|
127
|
+
@password
|
128
|
+
end
|
129
|
+
|
130
|
+
# sets the collection name for the class in which this module is extended
|
131
|
+
def collection_name=(collection_name)
|
132
|
+
if collection_name != self.collection_name
|
133
|
+
@collection_name = collection_name
|
134
|
+
end
|
135
|
+
@collection_name
|
136
|
+
end
|
137
|
+
|
138
|
+
# sets the elment name for the class in which this module is extended
|
139
|
+
def element_name=(element_name)
|
140
|
+
if element_name != self.element_name
|
141
|
+
@element_name = element_name
|
142
|
+
end
|
143
|
+
@element_name
|
144
|
+
end
|
145
|
+
|
146
|
+
# collection name for the class in which this module is extended
|
147
|
+
def collection_name
|
148
|
+
@collection_name || class_name.underscore.pluralize
|
149
|
+
end
|
150
|
+
|
151
|
+
# element name for the class in which this module is extended
|
152
|
+
def element_name
|
153
|
+
@element_name || class_name.underscore
|
154
|
+
end
|
155
|
+
|
156
|
+
# def all_attributes_set?
|
157
|
+
# site && user && password
|
158
|
+
# end
|
159
|
+
|
160
|
+
# routes to active resource find
|
161
|
+
def find(*args)
|
162
|
+
scope = args.slice!(0)
|
163
|
+
options = args.slice!(0) || {}
|
164
|
+
@resource_class.find(scope, options)
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
# creates an active resource class dynamically. All the attributes are set automatically. Avoid calling
|
169
|
+
# this method directly
|
170
|
+
def create_resource_class
|
171
|
+
# raise exceptions if site is not set
|
172
|
+
raise "Please set the site for #{self} class." unless(self.site)
|
173
|
+
|
174
|
+
created_class = Class.new(MingleResource)
|
175
|
+
|
176
|
+
# set the resource options
|
177
|
+
created_class.site = self.site
|
178
|
+
created_class.user = self.user
|
179
|
+
created_class.password = self.password
|
180
|
+
created_class.collection_name = self.collection_name
|
181
|
+
created_class.element_name = self.element_name
|
182
|
+
|
183
|
+
# created_class_name = "#{self}::#{class_name}#{Mingle4r::Helpers.fast_token()}"
|
184
|
+
created_class_name = class_name + Mingle4r::Helpers.fast_token()
|
185
|
+
created_class = self.const_set(created_class_name, created_class)
|
186
|
+
# eval "#{created_class_name} = created_class"
|
187
|
+
|
188
|
+
# includes a module called InstanceMethods in the class created dynamically
|
189
|
+
# if it is defined inside the wrapper class
|
190
|
+
inst_meth_mod_name = instance_methods_module_name()
|
191
|
+
created_class.send(:include, self.const_get(inst_meth_mod_name.to_sym)) if inst_meth_mod_name
|
192
|
+
created_class.send(:include, Mingle4r::CommonDynClassInstanceMethods)
|
193
|
+
|
194
|
+
# extends the class created dynamically with a module called ClassMethods if
|
195
|
+
# it is defined inside the wrapper class
|
196
|
+
class_meth_mod_name = class_methods_module_name()
|
197
|
+
created_class.extend(self.const_get(class_meth_mod_name)) if class_meth_mod_name
|
198
|
+
|
199
|
+
created_class
|
200
|
+
end
|
201
|
+
|
202
|
+
def class_name
|
203
|
+
self.name.split('::')[-1]
|
204
|
+
end
|
205
|
+
|
206
|
+
def instance_methods_module_name
|
207
|
+
inst_meth_mod_name = 'InstanceMethods'
|
208
|
+
self.constants.detect { |const| const.split('::')[-1] =~ /#{inst_meth_mod_name}/ }
|
209
|
+
end
|
210
|
+
|
211
|
+
def class_methods_module_name
|
212
|
+
class_meth_mod_name = 'ClassMethods'
|
213
|
+
self.constants.detect { |const| const.split('::')[-1] =~ /#{class_meth_mod_name}/ }
|
214
|
+
end
|
215
|
+
|
216
|
+
def method_missing(meth_id, *args, &block)
|
217
|
+
@resource_class.send(meth_id.to_sym, *args, &block)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Mingle4r
|
2
|
+
module Helpers
|
3
|
+
def Helpers.fast_token
|
4
|
+
values = [
|
5
|
+
rand(0x0010000),
|
6
|
+
rand(0x0010000),
|
7
|
+
rand(0x0010000),
|
8
|
+
rand(0x0010000),
|
9
|
+
rand(0x0010000),
|
10
|
+
rand(0x1000000),
|
11
|
+
rand(0x1000000),
|
12
|
+
]
|
13
|
+
"%04x%04x%04x%04x%04x%06x%06x" % values
|
14
|
+
end
|
15
|
+
|
16
|
+
def Helpers.encode2html(string)
|
17
|
+
html_char_map = {
|
18
|
+
'[' => '%5B', ']' => '%5D',
|
19
|
+
'(' => '%28', ')' => '%29',
|
20
|
+
',' => '%2C', ' ' => '%20',
|
21
|
+
'=' => '%3D', '\'' => '%27',
|
22
|
+
'<' => '%3C', '>' => '%3E',
|
23
|
+
}
|
24
|
+
|
25
|
+
string.strip! if string
|
26
|
+
encoded_string = ''
|
27
|
+
string.each_char do |char|
|
28
|
+
encoded_string << (html_char_map[char] || char)
|
29
|
+
end
|
30
|
+
encoded_string
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Mingle4r
|
2
|
+
class MingleClient
|
3
|
+
attr_reader :site, :user, :password, :proj_id
|
4
|
+
|
5
|
+
def initialize(site, user, password, proj_id = nil)
|
6
|
+
@site = site
|
7
|
+
@user = user
|
8
|
+
@password = password
|
9
|
+
@proj_id = proj_id
|
10
|
+
set_resource_attributes()
|
11
|
+
end
|
12
|
+
|
13
|
+
def site=(site)
|
14
|
+
if site != self.site
|
15
|
+
@site = site
|
16
|
+
uri = URI.parse(site)
|
17
|
+
@user = URI.decode(uri.user) if(uri.user)
|
18
|
+
@password = URI.decode(uri.password) if(uri.password)
|
19
|
+
set_resource_attributes()
|
20
|
+
end
|
21
|
+
@site
|
22
|
+
end
|
23
|
+
|
24
|
+
def user=(user)
|
25
|
+
if user != self.user
|
26
|
+
@user = user
|
27
|
+
set_resource_attributes()
|
28
|
+
end
|
29
|
+
@user
|
30
|
+
end
|
31
|
+
|
32
|
+
def password=(password)
|
33
|
+
if password != self.password
|
34
|
+
@password = password
|
35
|
+
set_resource_attributes()
|
36
|
+
end
|
37
|
+
@password
|
38
|
+
end
|
39
|
+
|
40
|
+
def proj_id=(proj_id)
|
41
|
+
if proj_id != @proj_id
|
42
|
+
@proj_id = proj_id
|
43
|
+
set_resource_attributes()
|
44
|
+
end
|
45
|
+
@proj_id
|
46
|
+
end
|
47
|
+
|
48
|
+
def valid_credentials?
|
49
|
+
project_class = @api.project_class
|
50
|
+
project_class.site = @api.base_url
|
51
|
+
project_class.user = user
|
52
|
+
project_class.password = password
|
53
|
+
begin
|
54
|
+
project_class.find(:all)
|
55
|
+
true
|
56
|
+
rescue Exception => e
|
57
|
+
e.message
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def project
|
62
|
+
raise 'proj_id attribute not set' unless @proj_id
|
63
|
+
@project = @api.project_class.find(@proj_id) unless(@project && (@proj_id == @project.identifier))
|
64
|
+
@project
|
65
|
+
end
|
66
|
+
|
67
|
+
def projects
|
68
|
+
@api.project_class.find(:all)
|
69
|
+
end
|
70
|
+
|
71
|
+
def users
|
72
|
+
@api.user_class.find(:all)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def set_resource_attributes
|
77
|
+
@api = API.create(@site)
|
78
|
+
set_attributes(@api.project_class)
|
79
|
+
set_attributes(@api.user_class)
|
80
|
+
end
|
81
|
+
|
82
|
+
def set_attributes(klass)
|
83
|
+
klass.site = @api.base_url
|
84
|
+
klass.user = @user
|
85
|
+
klass.password = @password
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# alias for the lazy ones
|
91
|
+
MingleClient = Mingle4r::MingleClient
|
data/lib/mingle4r.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
$:.unshift File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'active_resource'
|
6
|
+
require 'net/http'
|
7
|
+
|
8
|
+
# This module should be used to interact with mingle. Look in the readme for examples.
|
9
|
+
module Mingle4r
|
10
|
+
AUTHOR = 'Asur'
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'mingle_resource'
|
14
|
+
require 'mingle4r/version'
|
15
|
+
require 'mingle4r/common_class_methods'
|
16
|
+
require 'mingle4r/common_dyn_class_instance_methods'
|
17
|
+
require 'mingle4r/helpers'
|
18
|
+
require 'mingle4r/mingle_client'
|
19
|
+
require 'mingle4r/api'
|
20
|
+
|
21
|
+
# Version 1 of api
|
22
|
+
require 'mingle4r/api/v1'
|
23
|
+
require 'mingle4r/api/v1/card'
|
24
|
+
require 'mingle4r/api/v1/card/attachment'
|
25
|
+
require 'mingle4r/api/v1/project'
|
26
|
+
require 'mingle4r/api/v1/property_definition'
|
27
|
+
require 'mingle4r/api/v1/transition_execution'
|
28
|
+
require 'mingle4r/api/v1/user'
|
29
|
+
require 'mingle4r/api/v1/wiki'
|
30
|
+
|
31
|
+
# version 2 of api
|
32
|
+
require 'mingle4r/api/v2'
|
33
|
+
require 'mingle4r/api/v2/card'
|
34
|
+
require 'mingle4r/api/v2/card/attachment'
|
35
|
+
require 'mingle4r/api/v2/card/comment'
|
36
|
+
require 'mingle4r/api/v2/card/transition'
|
37
|
+
require 'mingle4r/api/v2/murmur'
|
38
|
+
require 'mingle4r/api/v2/project'
|
39
|
+
require 'mingle4r/api/v2/property_definition'
|
40
|
+
require 'mingle4r/api/v2/user'
|
41
|
+
require 'mingle4r/api/v2/wiki'
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mingle4r
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- asur
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-07 00:00:00 +05:30
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activeresource
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: " A connector wrapper for connecting to Mingle(http://studios.thoughtworks.com/mingle-agile-project-management).\n It uses active resource to handle the restful connections to Mingle. Makes the job of connecting to Mingle a \n lot easier. Also since it uses lazy evaluation, resources are fetched only when they are requested.\n"
|
26
|
+
email: arusarka@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
files:
|
34
|
+
- lib/mingle4r.rb
|
35
|
+
- lib/mingle_resource.rb
|
36
|
+
- lib/mingle4r/api.rb
|
37
|
+
- lib/mingle4r/common_class_methods.rb
|
38
|
+
- lib/mingle4r/common_dyn_class_instance_methods.rb
|
39
|
+
- lib/mingle4r/helpers.rb
|
40
|
+
- lib/mingle4r/mingle_client.rb
|
41
|
+
- lib/mingle4r/version.rb
|
42
|
+
- lib/mingle4r/api/v1.rb
|
43
|
+
- lib/mingle4r/api/v1/card.rb
|
44
|
+
- lib/mingle4r/api/v1/card/attachment.rb
|
45
|
+
- lib/mingle4r/api/v1/project.rb
|
46
|
+
- lib/mingle4r/api/v1/property_definition.rb
|
47
|
+
- lib/mingle4r/api/v1/transition_execution.rb
|
48
|
+
- lib/mingle4r/api/v1/user.rb
|
49
|
+
- lib/mingle4r/api/v1/wiki.rb
|
50
|
+
- lib/mingle4r/api/v2.rb
|
51
|
+
- lib/mingle4r/api/v2/card.rb
|
52
|
+
- lib/mingle4r/api/v2/card/attachment.rb
|
53
|
+
- lib/mingle4r/api/v2/card/comment.rb
|
54
|
+
- lib/mingle4r/api/v2/card/transition.rb
|
55
|
+
- lib/mingle4r/api/v2/murmur.rb
|
56
|
+
- lib/mingle4r/api/v2/project.rb
|
57
|
+
- lib/mingle4r/api/v2/property_definition.rb
|
58
|
+
- lib/mingle4r/api/v2/user.rb
|
59
|
+
- lib/mingle4r/api/v2/wiki.rb
|
60
|
+
- MIT-LICENSE
|
61
|
+
- History.txt
|
62
|
+
- README
|
63
|
+
- TODO.txt
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/arusarka/mingle4r/
|
66
|
+
licenses: []
|
67
|
+
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.5
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Mingle connector using active resource
|
92
|
+
test_files: []
|
93
|
+
|