mingle4r 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,5 @@
1
+ module Mingle4r
2
+ # common dynamic class instance methods
3
+ module CommonDynClassInstanceMethods
4
+ end
5
+ 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
@@ -0,0 +1,11 @@
1
+ module Mingle4r
2
+ module Version
3
+ Major = '0'
4
+ Minor = '3'
5
+ Tiny = '0'
6
+
7
+ def self.to_s
8
+ Major + '.' + Minor + '.' + Tiny
9
+ end
10
+ end
11
+ end
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'
@@ -0,0 +1,2 @@
1
+ # to avoid writing ActiveResource::Base
2
+ MingleResource = ActiveResource::Base
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
+