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 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