mingle4r 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,40 @@
1
+ 0.3.0
2
+ -----
3
+
4
+ * Major refactoring. The internal structure is completely changed
5
+ * supports both Mingle 2 and Mingle 3. Mingle 2 support is deprecated and will be removed in the next release.
6
+ * new Mingle 3 api features added - murmurs, comment
7
+
8
+ 0.2.2
9
+ -----
10
+
11
+ * added add_comment to card class. allows adding comment to a card
12
+
13
+ 0.2.1
14
+ -----
15
+
16
+ * added option to relationship methods(e.g. - cards, users, attachments) to return cached or
17
+ updated results
18
+ * property_definitions is a relationship method of project instead of mingle client.
19
+
20
+ 0.2.0
21
+ -----
22
+
23
+ * added class method apply_filter to Card class. allows an MQL filter
24
+ * added instance method execute_transition to Card class. allows to execute a transition on a card.
25
+
26
+ 0.1.6
27
+ -----
28
+
29
+ * added instance method at_version to Card class. gets the particular version for the card
30
+
31
+ 0.1.5
32
+ -----
33
+
34
+ * Rest Api's added - wiki
35
+
36
+ 0.0.1
37
+ -----
38
+
39
+ * Rest Api's - Card, Project, User, Attachment, Property Definition
40
+ * Mingle Client - supports getting cards, project etc.
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009 Arusarka Haldar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,227 @@
1
+ == mingle4r
2
+
3
+ http://github.com/arusarka/mingle4r/tree/master
4
+
5
+ == DESCRIPTION:
6
+
7
+ This gem is a wrapper around active resource to access the rest api exposed by mingle
8
+ (http://studios.thoughtworks.com/mingle-agile-project-management).It provides a easy
9
+ way to communicate with mingle. For the library to work you need to enable basic authentication
10
+ (not enabled by default) in Mingle. See below to enable basic authentication in Mingle.
11
+
12
+ However if you are planning to connect and work with mingle from the terminal, then there
13
+ is another gem mingle-mingle which you should look at. This library provides a very easy
14
+ api to write code to work with mingle (see the examples below) but thats it.
15
+
16
+ Enable basic authentication in Mingle
17
+ -------------------------------------
18
+
19
+ 1) Go to Mingle DataDir
20
+
21
+ 2) Open YAML file <Mingle DataDir>/config/auth_config.yml
22
+
23
+ 3) Set 'basic_authentication_enabled' to 'true' (without the quotes) if it is not so
24
+
25
+ == FEATURES/PROBLEMS:
26
+
27
+ It gives you access to projects in the mingle instance, cards under the project and also
28
+ attachments for a particular card.
29
+
30
+ == SYNOPSIS:
31
+
32
+ The api now supports both mingle 2 and mingle 3. The gem tries as much as possible to hide
33
+ away the internal details. But some api features are only supported in mingle 3 only (like
34
+ murmurs). For that check the api documentation for the mingle instance(located at
35
+ <mingle instance host>/help/index)
36
+
37
+ In all the documentation below you can replace Mingle4r::MingleClient with MingleClient.
38
+ Its an alias for easy use.
39
+
40
+ A) Getting all the projects for a particular instance
41
+ -----------------------------------------------------
42
+
43
+ Suppose you want to connect to the mingle instance hosted at http://localhost:8080 where the
44
+ username is 'testuser' and password is 'password'.
45
+
46
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
47
+ projs = m_c.projects
48
+
49
+ projs is an array of active resource objects
50
+
51
+ B) Getting a particular project
52
+ -------------------------------
53
+
54
+ Before you access a particular project you need to set the project id for the mingle client
55
+ object. You can do that in two ways. Supposing you are trying to access a project with an
56
+ identifier of 'great_mingle_project'
57
+
58
+ WARNING : project identifier and project name are different. If you named your project as
59
+ 'Great Mingle Project' it's identifier is by default 'great_mingle_project'. To be sure what
60
+ the identifier of a project is you should look at the url in mingle in the particular project
61
+ you are trying to access. It should be something like 'http://localhost:8080/projects/great_mingle_project'
62
+
63
+ 1) Set at initialize time
64
+
65
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password',
66
+ 'great_mingle_project')
67
+ m_c.project
68
+
69
+ 2) Set an attribute later
70
+
71
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
72
+ m_c.proj_id = 'great_mingle_project'
73
+ m_c.project
74
+
75
+ C) Getting cards for a particular project
76
+ --------------------------------------
77
+
78
+ Get a mingle client object initialized as in SECTION B. Then call the cards method.
79
+
80
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
81
+ m_c.proj_id = 'great_mingle_project'
82
+ m_c.project.cards
83
+
84
+ cards will be an array of activeresoure objects.
85
+
86
+ D) Getting custom properties for a card
87
+ ---------------------------------------
88
+
89
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
90
+ m_c.proj_id = 'great_mingle_project'
91
+ card = m_c.project.cards[0]
92
+ card.custom_properties => returns an array of hashes, {property name => property value}
93
+
94
+ However this gives only custom properties, not all the properties.
95
+
96
+ E) Getting a particular property
97
+ --------------------------------
98
+
99
+ gets the value of a property. The property name given should be the same as seen in Mingle.
100
+
101
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
102
+ m_c.proj_id = 'great_mingle_project'
103
+ card = m_c.project.cards[0]
104
+ card.property_value('Status')
105
+
106
+ F) Setting a particular property
107
+ --------------------------------
108
+
109
+ sets the value of the property. The property name given should be the same as in Mingle and
110
+ the value given should be one of the values that Mingle accepts in case of a managed list
111
+
112
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
113
+ m_c.proj_id = 'great_mingle_project'
114
+ defect_card = m_c.project.cards.first
115
+ defect_card.property_value('Status', 'Closed')
116
+
117
+ G) Adding comment to a particular card
118
+ --------------------------------------
119
+
120
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
121
+ m_c.proj_id = 'great_mingle_project'
122
+ defect_card = m_c.project.cards[0]
123
+ defect_card.add_comment('Not able to reproduce')
124
+
125
+ H) Getting all comments for a card(only in mingle 3.0)
126
+ ------------------------------------------------------
127
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
128
+ m_c.proj_id = 'great_mingle_project'
129
+ defect_card = m_c.project.cards.first
130
+ defect_cards.comments
131
+
132
+ I) Attachments
133
+ --------------
134
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
135
+ m_c.proj_id = 'great_mingle_project'
136
+ defect_card = m_c.project.cards.first
137
+ defect_card.attachments
138
+
139
+ 1) Downloading a particular attachment
140
+ --------------------------------------
141
+
142
+ attachment = defect_card.attachments.first
143
+ attachment.save('page.css')
144
+
145
+ 2) Uploading an attachment
146
+ --------------------------
147
+
148
+ defect_card.upload_attachment('page-screenshot.jpg')
149
+
150
+ J) Murmurs(only in Mingle 3.0)
151
+ ------------------------------
152
+
153
+ 1) Get the murmurs for a project
154
+ --------------------------------
155
+
156
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
157
+ m_c.proj_id = 'great_mingle_project'
158
+ project = m_c.project
159
+ project.murmurs
160
+
161
+ 2) Get the murmurs associated with a card
162
+ -----------------------------------------
163
+
164
+ card = project.cards.first
165
+ card.murmurs
166
+
167
+ 3) post a murmur(hooray!)
168
+ -------------------------
169
+ project.post_murmur('my first murmur, I am excited!')
170
+
171
+ K) Get all transitions for a card(only in Mingle 3.0)
172
+ -----------------------------------------------------
173
+
174
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
175
+ m_c.proj_id = 'great_mingle_project'
176
+ defect_card = m_c.project.cards.first
177
+
178
+ defect_card.transitions
179
+
180
+ L) Execute a transition on a card
181
+ ---------------------------------
182
+
183
+ m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
184
+ m_c.proj_id = 'great_mingle_project'
185
+ defect_card = m_c.project.cards.first
186
+
187
+ defect_card.execute_transition(
188
+ 'name'/'transition' => name of the transition to execute exactly s in Mingle(required in 2,3 but
189
+ not required in 3.0)
190
+ 'comment' => comment for the transition, required only if the transition requires a comment
191
+ 'Property Name as in Mingle exactly' => 'Property value to set for the property', required only
192
+ if the transition requires to be set manually.
193
+ )
194
+
195
+ == REQUIREMENTS:
196
+
197
+ 1) active_resource gem, it would be automatically taken care of
198
+ during gem install.
199
+
200
+ == INSTALL:
201
+
202
+ sudo (not on windows) gem install mingle4r
203
+
204
+ == LICENSE:
205
+
206
+ (The MIT License)
207
+
208
+ Copyright (c) 2009 Arusarka Haldar
209
+
210
+ Permission is hereby granted, free of charge, to any person obtaining
211
+ a copy of this software and associated documentation files (the
212
+ 'Software'), to deal in the Software without restriction, including
213
+ without limitation the rights to use, copy, modify, merge, publish,
214
+ distribute, sublicense, and/or sell copies of the Software, and to
215
+ permit persons to whom the Software is furnished to do so, subject to
216
+ the following conditions:
217
+
218
+ The above copyright notice and this permission notice shall be
219
+ included in all copies or substantial portions of the Software.
220
+
221
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
222
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
223
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
224
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
225
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
226
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
227
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/TODO.txt ADDED
@@ -0,0 +1,7 @@
1
+ update documentation
2
+ write tests for mingle4r/mingle_client
3
+
4
+ refactorings
5
+ ------------
6
+ remove calling create_resource_class through send
7
+ remove checking for cache through a variable. check the results container directly
@@ -0,0 +1,51 @@
1
+ module Mingle4r
2
+ class API
3
+ class V1
4
+ class Card
5
+ class Attachment
6
+ module InstanceMethods
7
+ # downloads the attachment. It an additional file path is given it saves it at the
8
+ # given path. The given path should be writable
9
+ def download(file_name = nil)
10
+ collection_uri = self.class.site
11
+ rel_down_url = self.url
12
+ base_url = "#{collection_uri.scheme}://#{collection_uri.host}:#{collection_uri.port}/"
13
+ down_uri = URI.join(base_url, rel_down_url)
14
+ req = Net::HTTP::Get.new(down_uri.path)
15
+ req.basic_auth self.class.user, self.class.password
16
+ begin
17
+ res = Net::HTTP.start(down_uri.host, down_uri.port) { |http| http.request(req) }
18
+ file_name ||= self.file_name()
19
+ File.open(file_name, 'w') { |f| f.print(res.body) }
20
+ rescue Exception => e
21
+ e.message
22
+ end
23
+ end # download
24
+
25
+ # alias for file_name
26
+ def name
27
+ file_name()
28
+ end
29
+
30
+ # so that active resource tries to find by proper id
31
+ def id
32
+ name()
33
+ end
34
+
35
+ # This method had to be overriden.
36
+ # normal active resource destroy doesn't work as mingle site for deleting attachments doesn't end with .xml.
37
+ def destroy
38
+ connection = self.send(:connection)
39
+ # deletes the attachment by removing .xml at the end
40
+ connection.delete(self.send(:element_path).gsub(/\.xml\z/, ''))
41
+ end
42
+ alias_method :delete, :destroy
43
+ end #module InstanceMethods
44
+
45
+ extend Mingle4r::CommonClassMethods
46
+
47
+ end # class Attachment
48
+ end # class Card
49
+ end # class V1
50
+ end # class API
51
+ end # module Mingle4r
@@ -0,0 +1,173 @@
1
+ module Mingle4r
2
+ class API
3
+ class V1
4
+ class Card
5
+ extend Mingle4r::CommonClassMethods
6
+
7
+ # overwrite the default find in CommonClassMethods
8
+ def self.find(*args)
9
+ scope = args.slice!(0)
10
+ options = args.slice!(0) || {}
11
+ @resource_class.find_without_pagination(scope, options)
12
+ end
13
+
14
+ module ClassMethods
15
+ def find_without_pagination(*args)
16
+ scope = args.slice!(0)
17
+ options = args.slice!(0) || {}
18
+ options[:params] ||= {}
19
+ options[:params].merge!({:page => 'all'})
20
+
21
+ # call ActiveResource::Base::find with proper options
22
+ find(scope, options)
23
+ end
24
+
25
+ # applies an mql filter on card types. Look at https://mingle05.thoughtworks.com/help/mql_reference.html
26
+ # for reference
27
+ def apply_filter(filter_string)
28
+ find_without_pagination(:all, :params => {'filters[mql]'.to_sym => filter_string})
29
+ end
30
+ end
31
+
32
+ module InstanceMethods
33
+ def attachments(refresh = false)
34
+ return @attachments if(!refresh && @attachments_cached)
35
+ attachment_site = File.join(self.class.site.to_s, "cards/#{self.number()}").to_s
36
+ Attachment.site = attachment_site
37
+ Attachment.user = self.class.user
38
+ Attachment.password = self.class.password
39
+ attachment_class = Attachment.send(:create_resource_class)
40
+ @attachments = attachment_class.find(:all)
41
+ @attachments_cached = true
42
+ @attachments
43
+ end
44
+
45
+ def upload_attachment(file_path)
46
+ attachment_uri = URI.parse(File.join(self.class.site.to_s, "cards/#{self.number()}/attachments.xml"))
47
+ http = Net::HTTP.new(attachment_uri.host, attachment_uri.port)
48
+ http.use_ssl = attachment_uri.is_a?(URI::HTTPS)
49
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl
50
+ basic_encode = 'Basic ' + ["#{self.class.user}:#{self.class.password}"].pack('m').delete("\r\n")
51
+
52
+ post_headers = {
53
+ 'Authorization' => basic_encode,
54
+ 'Content-Type' => 'multipart/form-data; boundary=----------XnJLe9ZIbbGUYtzPQJ16u1'
55
+ }
56
+
57
+ file_content = IO.read(file_path)
58
+
59
+ post_body = <<EOS
60
+ ------------XnJLe9ZIbbGUYtzPQJ16u1\r
61
+ Content-Disposition: form-data; name="file"; filename="#{File.basename(file_path)}"\r
62
+ Content-Type: application/octet-stream\r
63
+ Content-Length: #{file_content.size}\r
64
+ \r
65
+ #{file_content}\r
66
+ ------------XnJLe9ZIbbGUYtzPQJ16u1--\r
67
+ EOS
68
+
69
+ http.post(attachment_uri.path, post_body, post_headers)
70
+ end
71
+
72
+ # returns back the version of the card given. If an invalid version is given, the latest
73
+ # version is returned, takes a number or :next or :before
74
+ def at_version(version_no)
75
+ version_2_find = 0
76
+ case version_no
77
+ when :before
78
+ version_2_find = self.version.to_i - 1
79
+ when :next
80
+ version_2_find = self.version.to_i + 1
81
+ else
82
+ version_2_find = version_no.to_i
83
+ end
84
+ self.class.find(self.number, :params => {:version => version_2_find})
85
+ end
86
+
87
+ # adds a comment to a card.
88
+ def add_comment(comment)
89
+ comment_uri = URI.parse(File.join(self.class.site.to_s, "cards/add_comment?card_id=#{self.id}"))
90
+
91
+ http = Net::HTTP.new(comment_uri.host, comment_uri.port)
92
+ http.use_ssl = comment_uri.is_a?(URI::HTTPS)
93
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl
94
+
95
+ basic_encode = 'Basic ' + ["#{self.class.user}:#{self.class.password}"].pack('m').delete("\r\n")
96
+
97
+ post_headers = {
98
+ 'Authorization' => basic_encode,
99
+ 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'
100
+ }
101
+
102
+ post_body = "comment=#{comment}&card_id=#{self.id}"
103
+
104
+ http.post(comment_uri.path, post_body, post_headers)
105
+ end
106
+
107
+ # Executes the given transition on the card.
108
+ # Example :
109
+ # defect_card.execute_transition(:name => 'Close Defect', :Owner => nil, :Status => 'Closed', :transition_comment => comment)
110
+ # transition_comment is mandatory if the transition is set that way.
111
+ # after transition 'Owner' would have value 'Not Set' and 'Status' would be 'Closed' for defect card
112
+ def execute_transition(args = {})
113
+ V1::TransitionExecution.site = self.class.site.to_s
114
+ V1::TransitionExecution.user = self.class.user
115
+ V1::TransitionExecution.password = self.class.password
116
+
117
+ args.symbolize_keys!
118
+ trans_hash = create_transition_exec_hash(args)
119
+ V1::TransitionExecution.new(trans_hash).execute
120
+ end
121
+
122
+ # gets the value of a property. The property name given should be the same name as
123
+ # the mingle property name
124
+ def property_value(name, val = nil)
125
+ set_property_definitions_attributes
126
+ column_name = PropertyDefinition.column_name_for(name.to_s)
127
+ val ? attributes[column_name] = val : attributes[column_name]
128
+ end
129
+
130
+ def custom_properties
131
+ set_property_definitions_attributes
132
+ custom_props = []
133
+ card_props = attributes.keys
134
+ PropertyDefinition.find(:all).each do |prop|
135
+ if(card_props.include?(prop.column_name))
136
+ custom_prop = {prop.name => attributes[prop.column_name]}
137
+ custom_props.push(custom_prop)
138
+ end
139
+ end
140
+ custom_props
141
+ end
142
+
143
+ private
144
+ def boundary
145
+ '----------XnJLe9ZIbbGUYtzPQJ16u1'
146
+ end
147
+
148
+ def create_transition_exec_hash(args)
149
+ transition_hash = {}
150
+ transition_hash['card'] = (args.delete(:card) || self.number).to_i
151
+ transition_hash['transition'] = (args.delete(:name) || args.delete(:transition))
152
+
153
+ comment = args.delete(:comment)
154
+ transition_hash['comment'] = comment if comment
155
+ properties = []
156
+ args.each do |name, value|
157
+ property = {'name' => name.to_s, 'value' => value}
158
+ properties.push(property)
159
+ end
160
+ transition_hash['properties'] = properties unless properties.empty?
161
+ transition_hash
162
+ end
163
+
164
+ def set_property_definitions_attributes
165
+ PropertyDefinition.site = self.class.site.to_s
166
+ PropertyDefinition.user = self.class.user
167
+ PropertyDefinition.password = self.class.password
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,71 @@
1
+ # require File.dirname(__FILE__) + '/../common/project'
2
+ module Mingle4r
3
+ class API
4
+ class V1
5
+ class Project
6
+
7
+ extend Mingle4r::CommonClassMethods
8
+
9
+ module InstanceMethods
10
+ # returns the cards for the project. To hit the resource server without returning
11
+ # cached results pass true as an argument.
12
+ def cards(refresh = false)
13
+ return @cards if(!refresh && @cards_cached)
14
+ cards_site = File.join(self.class.site.to_s, "projects/#{self.identifier()}")
15
+ # card_class = API.new(self.class.site).card_class
16
+ Card.site = cards_site
17
+ Card.user = self.class.user
18
+ Card.password = self.class.password
19
+ # @cards = Card.send(:create_resource_class).find_without_pagination(:all)
20
+ @cards = Card.find_without_pagination(:all)
21
+ @cards_cached = true
22
+ @cards
23
+ end
24
+
25
+ # returns the users for the project. To hit the resource server without returning
26
+ # cached results pass true as an argument.
27
+ def users(refresh = false)
28
+ return @users if(!refresh && @users_cached)
29
+ users_site = File.join(self.class.site.to_s, "projects/#{self.identifier()}")
30
+ User.site = users_site
31
+ User.user = self.class.user
32
+ User.password = self.class.password
33
+ User.element_name = nil # reset
34
+ user_class = User.send(:create_resource_class)
35
+ @users = user_class.find(:all)
36
+ @users_cached = true
37
+ @users
38
+ end
39
+
40
+ # returns the wikis for the project. To hit the resource server without returning
41
+ # cached results pass true as an argument.
42
+ def wikis(refresh = false)
43
+ return @wikis if(!refresh && @wikis_cached)
44
+ wiki_site = File.join(self.class.site.to_s, "projects/#{self.identifier()}")
45
+ Wiki.site = wiki_site
46
+ Wiki.user = self.class.user
47
+ Wiki.password = self.class.password
48
+ wiki_class = Wiki.send(:create_resource_class)
49
+ @wikis = wiki_class.find(:all)
50
+ @wikis_cached = true
51
+ @wikis
52
+ end
53
+
54
+ # returns the property definitions for the project. To hit the resource server
55
+ # pass true as an argument
56
+ def property_definitions(refresh = false)
57
+ return @prop_definitions if(!refresh && @prop_definitions_cached)
58
+ properties_site = File.join(self.class.site.to_s, "/projects/#{self.identifier}")
59
+ PropertyDefinition.site = properties_site
60
+ PropertyDefinition.user = self.class.user
61
+ PropertyDefinition.password = self.class.password
62
+ prop_defn_class = PropertyDefinition.send(:create_resource_class)
63
+ @prop_definitions = prop_defn_class.find(:all)
64
+ @prop_definitions_cached = true
65
+ @prop_definitions
66
+ end
67
+ end # module InstanceMethods
68
+ end # class Project
69
+ end # class V1
70
+ end # class API
71
+ end
@@ -0,0 +1,16 @@
1
+ module Mingle4r
2
+ class API
3
+ class V1
4
+ class PropertyDefinition
5
+ extend Mingle4r::CommonClassMethods
6
+
7
+ def self.column_name_for(prop_name)
8
+ property_def = @resource_class.find(:all).detect { |prop| prop.name == prop_name }
9
+ property_def ? property_def.column_name : nil
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ Mingle4r::API::V1::PropertyDefinition.element_name = 'record'
@@ -0,0 +1,15 @@
1
+ module Mingle4r
2
+ class API
3
+ class V1
4
+ class TransitionExecution
5
+ extend Mingle4r::CommonClassMethods
6
+ module InstanceMethods
7
+ def execute
8
+ conn = self.class.connection
9
+ conn.post(self.class.collection_path, encode, self.class.headers)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Mingle4r
2
+ class API
3
+ class V1
4
+ class User
5
+ extend Mingle4r::CommonClassMethods
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module Mingle4r
2
+ class API
3
+ class V1
4
+ class Wiki
5
+ extend Mingle4r::CommonClassMethods
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ Mingle4r::API::V1::Wiki.collection_name = 'wiki'
12
+ Mingle4r::API::V1::Wiki.element_name = 'page'
@@ -0,0 +1,25 @@
1
+ module Mingle4r
2
+ class API
3
+ class V1
4
+ def initialize(host_url)
5
+ @host_uri = URI.parse(host_url)
6
+ end
7
+
8
+ def base_url
9
+ @host_uri.to_s
10
+ end
11
+
12
+ def version
13
+ 1
14
+ end
15
+
16
+ def project_class
17
+ Project
18
+ end
19
+
20
+ def user_class
21
+ User
22
+ end
23
+ end
24
+ end
25
+ end