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