rally_api 0.4.1 → 0.5.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/README.rdoc +103 -92
- data/lib/rally_api/{time_machine_query.rb → lookback_api_query.rb} +16 -21
- data/lib/rally_api/rally_json_connection.rb +5 -2
- data/lib/rally_api/rally_object.rb +25 -13
- data/lib/rally_api/rally_query.rb +20 -12
- data/lib/rally_api/rally_query_result.rb +2 -0
- data/lib/rally_api/rally_rest_json.rb +103 -32
- data/lib/rally_api/version.rb +2 -1
- metadata +5 -5
data/README.rdoc
CHANGED
@@ -1,102 +1,113 @@
|
|
1
|
-
RallyAPI (rally_api)
|
1
|
+
= RallyAPI (rally_api) -- a faster Rally REST api wrapper
|
2
2
|
|
3
|
-
==Description
|
3
|
+
== Description
|
4
4
|
|
5
|
-
RallyAPI is a wrapper of Rally's Web Service API Json endpoints
|
5
|
+
RallyAPI is a wrapper of Rally's Web Service API Json endpoints using rest-client and native json parsing
|
6
6
|
|
7
7
|
== Installation
|
8
|
-
|
9
|
-
gem install rest-client
|
10
|
-
gem install json
|
11
|
-
gem install rally_api
|
12
|
-
|
13
|
-
** Note if you are on Windows - you will need DevKit from http://rubyinstaller.org to properly install the json gem
|
14
|
-
** - that native compiled parsing gives us some speed.
|
15
|
-
** - Follow the instructions here to install DevKit: https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
|
8
|
+
gem install rally_api
|
16
9
|
|
17
10
|
== Usage
|
18
11
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
headers
|
24
|
-
headers.
|
25
|
-
headers.
|
26
|
-
|
27
|
-
|
28
|
-
config = {:base_url => "https://rally1.rallydev.com/slm"}
|
29
|
-
config[:username] = "user@company.com"
|
30
|
-
config[:password] = "password"
|
31
|
-
config[:workspace] = "Workspace Name"
|
32
|
-
config[:project] = "Project Name"
|
33
|
-
config[:headers] = headers #from RallyAPI::CustomHttpHeader.new()
|
34
|
-
|
35
|
-
@rally = RallyAPI::RallyRestJson.new(config)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
test_query
|
40
|
-
test_query.
|
41
|
-
test_query.
|
42
|
-
test_query.
|
43
|
-
test_query.
|
44
|
-
test_query.
|
45
|
-
test_query.
|
46
|
-
test_query.
|
47
|
-
test_query.
|
48
|
-
test_query.
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
#
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
12
|
+
=== Making a connection to Rally
|
13
|
+
require 'rally_api'
|
14
|
+
|
15
|
+
#Setting custom headers
|
16
|
+
headers = RallyAPI::CustomHttpHeader.new()
|
17
|
+
headers.name = "My Utility"
|
18
|
+
headers.vendor = "MyCompany"
|
19
|
+
headers.version = "1.0"
|
20
|
+
|
21
|
+
config = {:base_url => "https://rally1.rallydev.com/slm"}
|
22
|
+
config[:username] = "user@company.com"
|
23
|
+
config[:password] = "password"
|
24
|
+
config[:workspace] = "Workspace Name"
|
25
|
+
config[:project] = "Project Name"
|
26
|
+
config[:headers] = headers #from RallyAPI::CustomHttpHeader.new()
|
27
|
+
|
28
|
+
@rally = RallyAPI::RallyRestJson.new(config)
|
29
|
+
|
30
|
+
|
31
|
+
=== Querying Rally
|
32
|
+
test_query = RallyAPI::RallyQuery.new()
|
33
|
+
test_query.type = :defect
|
34
|
+
test_query.fetch = "Name"
|
35
|
+
test_query.workspace = {"_ref" => "https://rally1.rallydev.com/slm/webservice/1.25/workspace/12345.js" } #optional
|
36
|
+
test_query.project = {"_ref" => "https://rally1.rallydev.com/slm/webservice/1.25/project/12345.js" } #optional
|
37
|
+
test_query.page_size = 200 #optional - default is 200
|
38
|
+
test_query.limit = 1000 #optional - default is 99999
|
39
|
+
test_query.project_scope_up = false
|
40
|
+
test_query.project_scope_down = true
|
41
|
+
test_query.order = "Name Asc"
|
42
|
+
test_query.query_string = "(Severity = \"High\")"
|
43
|
+
|
44
|
+
results = @rally.find(test_query)
|
45
|
+
|
46
|
+
#tip - set the fetch string of the query to the fields you need -
|
47
|
+
#only resort to the read method if you want your code to be slow
|
48
|
+
results.each do |defect|
|
49
|
+
puts defect.Name # or defect["Name"]
|
50
|
+
defect.read #read the whole defect from Rally to get all fields (eg Severity)
|
51
|
+
puts defect.Severity
|
52
|
+
end
|
53
|
+
|
54
|
+
#for people comfortable passing around blocks:
|
55
|
+
results = @rally.find do |q|
|
56
|
+
q.type = :defect
|
57
|
+
q.fetch = "Name,FormattedID"
|
58
|
+
q.query_string = "(Priority = \"Low\")"
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
=== Reading an Artifact
|
63
|
+
defect = @rally.read(:defect, 12345) #by ObjectID
|
64
|
+
#or
|
65
|
+
defect = @rally.read(:defect, "FormattedID|DE42") #by FormattedID
|
66
|
+
#or if you already have an object like from a query
|
67
|
+
results = @rally.find(RallyAPI::RallyQuery.new({:type => :defect, :query_string => "(FormattedID = DE42)"}))
|
68
|
+
defect = results.first
|
69
|
+
defect.read
|
70
|
+
|
71
|
+
puts defect["Name"]
|
72
|
+
#or - fields can be read by bracket artifact["FieldDisplayName"] or artifact.FieldDisplayName
|
73
|
+
puts defect.Name
|
74
|
+
|
75
|
+
#An Important note about reading fields and fetching:
|
76
|
+
#If you query with a specific fetch string, for example query defect and fetch Name,Severity,Description
|
77
|
+
#You will *only* get back those fields defect.Priority will be nil, but may not be null in Rally
|
78
|
+
#Use object.read or @rally.read to make sure you read the whole object if you want what is in Rally
|
79
|
+
# This is done for speed - lazy loading (going back to get a value from Rally) can be unneccessarily slow
|
80
|
+
# *Pick you fetch strings wisely* fetch everything you need and don't rely on read if you don't need it the speed is worth it.
|
81
|
+
|
82
|
+
=== Creating an Artifact
|
83
|
+
obj = {}
|
84
|
+
obj["Name"] = "Test Defect created #{DateTime.now()}"
|
85
|
+
new_de = @rally.create(:defect, obj)
|
86
|
+
puts new_de["FormattedID"]
|
87
|
+
|
88
|
+
=== Updating an Artifact
|
89
|
+
fields = {}
|
90
|
+
fields["Severity"] = "Critical"
|
91
|
+
fields["Description"] = "Description for the issue"
|
92
|
+
updated_defect = @rally.update(:defect, 12345, fields) #by ObjectID
|
93
|
+
#or
|
94
|
+
updated_defect = @rally.update(:defect, "FormattedID|DE42", fields) #by FormattedID
|
95
|
+
# or
|
96
|
+
defect = @rally.read(:defect, 12345) #by lookup then udpating via the object
|
97
|
+
field_updates = {"Description" => "Changed Description"}
|
98
|
+
defect.update(field_updates)
|
99
|
+
|
100
|
+
=== Utils
|
101
|
+
#allowed values: pass the Artifact type string or downcased symbol and the Display Name of the field
|
102
|
+
@rally.allowed_values("Defect", "Severity")
|
103
|
+
@rally.allowed_values(:story, "ScheduleState")
|
104
|
+
|
105
|
+
#re-ranking: rank_above and rank_below
|
106
|
+
story1.rank_above(story2) #in a drag and drop workspace move story1 relative to story2
|
107
|
+
story1.rank_below(story2)
|
108
|
+
|
109
|
+
#== License/Meta
|
110
|
+
#Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
|
100
111
|
#Copyright (c) 2002-2011 Rally Software Development Corp. All Rights Reserved.
|
101
112
|
#Your use of this Software is governed by the terms and conditions
|
102
113
|
#of the applicable Subscription Agreement between your company and
|
@@ -1,39 +1,34 @@
|
|
1
|
+
# :stopdoc:
|
1
2
|
#Copyright (c) 2002-2012 Rally Software Development Corp. All Rights Reserved.
|
2
3
|
#Your use of this Software is governed by the terms and conditions
|
3
4
|
#of the applicable Subscription Agreement between your company and
|
4
5
|
#Rally Software Development Corp.
|
6
|
+
# :startdoc:
|
7
|
+
|
5
8
|
module RallyAPI
|
6
9
|
# query is like:
|
7
10
|
# query_hash = {}
|
8
|
-
# query_hash[
|
9
|
-
# query_hash[
|
10
|
-
# query_hash[
|
11
|
-
# query_hash[
|
12
|
-
# query_hash[
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# query_hash[:stopafter]
|
18
|
-
|
19
|
-
class TimeMachineQuery
|
20
|
-
attr_accessor :workspace
|
11
|
+
# query_hash["find"] = { some json for a query} or true
|
12
|
+
# query_hash["fields"] = ["State", "PlanEstimate"]
|
13
|
+
# query_hash["pagesize"] = 1000
|
14
|
+
# query_hash["sort"] = { _id: 1 }
|
15
|
+
# query_hash["workspace"] = workspace oid for query uri
|
16
|
+
|
17
|
+
#query info is the master hash instead of a bunch of instance variables
|
18
|
+
class LookbackAPIQuery
|
19
|
+
attr_accessor :query_info
|
21
20
|
|
22
21
|
def initialize(query_hash = nil)
|
22
|
+
@query_info = nil
|
23
23
|
parse_query_hash(query_hash) if !query_hash.nil?
|
24
24
|
self
|
25
25
|
end
|
26
26
|
|
27
27
|
def make_query_params
|
28
28
|
query_params = {}
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
#query_params[:project] = @project["_ref"] if !@project.nil?
|
33
|
-
#query_params[:projectScopeUp] = @project_scope_up
|
34
|
-
#query_params[:projectScopeDown] = @project_scope_down
|
35
|
-
#query_params[:order] = @order
|
36
|
-
#query_params[:pagesize] = @page_size
|
29
|
+
query_params[:find] = @query_string
|
30
|
+
query_params[:workspace] = @workspace["_ref"] if !@workspace.nil?
|
31
|
+
query
|
37
32
|
|
38
33
|
query_params
|
39
34
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'rest_client'
|
2
2
|
require 'json'
|
3
3
|
|
4
|
+
# :stopdoc:
|
4
5
|
#Copyright (c) 2002-2012 Rally Software Development Corp. All Rights Reserved.
|
5
6
|
#Your use of this Software is governed by the terms and conditions
|
6
7
|
#of the applicable Subscription Agreement between your company and
|
7
8
|
#Rally Software Development Corp.
|
9
|
+
# :startdoc:
|
10
|
+
|
8
11
|
module RallyAPI
|
9
12
|
|
10
13
|
|
@@ -169,13 +172,13 @@ module RallyAPI
|
|
169
172
|
@retry_list[req.url] += 1
|
170
173
|
retry
|
171
174
|
end
|
172
|
-
raise msg
|
175
|
+
raise StandardError, msg
|
173
176
|
end
|
174
177
|
@retry_list.delete(req.url)
|
175
178
|
puts response if @low_debug
|
176
179
|
json_obj = JSON.parse(response.body) #todo handle null post error
|
177
180
|
errs = check_for_errors(json_obj)
|
178
|
-
raise "\nError on request - #{url} - \n#{errs}" if errs[:errors].length > 0
|
181
|
+
raise StandardError, "\nError on request - #{url} - \n#{errs}" if errs[:errors].length > 0
|
179
182
|
json_obj
|
180
183
|
end
|
181
184
|
|
@@ -1,9 +1,18 @@
|
|
1
|
+
# :stopdoc:
|
1
2
|
#Copyright (c) 2002-2012 Rally Software Development Corp. All Rights Reserved.
|
2
3
|
#Your use of this Software is governed by the terms and conditions
|
3
4
|
#of the applicable Subscription Agreement between your company and
|
4
5
|
#Rally Software Development Corp.
|
6
|
+
# :startdoc:
|
7
|
+
|
5
8
|
module RallyAPI
|
6
9
|
|
10
|
+
#todo add rankTo bottom and top
|
11
|
+
#https://trial.rallydev.com/slm/webservice/x/defect/oid.js?rankTo=BOTTOM
|
12
|
+
#https://trial.rallydev.com/slm/webservice/x/defect/oid.js?rankTo=TOP
|
13
|
+
|
14
|
+
# RallyObject is a helper class that wraps the JSON.parsed hash
|
15
|
+
#
|
7
16
|
class RallyObject
|
8
17
|
|
9
18
|
attr_reader :rally_object
|
@@ -37,6 +46,10 @@ module RallyAPI
|
|
37
46
|
end
|
38
47
|
|
39
48
|
def getref
|
49
|
+
ref
|
50
|
+
end
|
51
|
+
|
52
|
+
def ref
|
40
53
|
@rally_object["_ref"]
|
41
54
|
end
|
42
55
|
|
@@ -54,22 +67,16 @@ module RallyAPI
|
|
54
67
|
|
55
68
|
private
|
56
69
|
|
70
|
+
# An attempt to be rally_rest_api user friendly -
|
71
|
+
# you can get a field the old way with an underscored field name or the upcase name
|
57
72
|
def method_missing(sym, *args)
|
58
|
-
get_val(sym.to_s)
|
73
|
+
ret_val = get_val(sym.to_s)
|
74
|
+
if @rally_rest.rally_rest_api_compat && ret_val.nil?
|
75
|
+
ret_val = get_val(camel_case_word(:sym))
|
76
|
+
end
|
77
|
+
ret_val
|
59
78
|
end
|
60
79
|
|
61
|
-
#the magic of lazy loading is gone
|
62
|
-
#def method_missing(sym, *args)
|
63
|
-
# return_val = get_val(sym.to_s)
|
64
|
-
#
|
65
|
-
# if return_val.nil?
|
66
|
-
# @rally_object = @rally_rest.reread(@rally_object)
|
67
|
-
# return_val = get_val(sym.to_s)
|
68
|
-
# end
|
69
|
-
#
|
70
|
-
# return_val
|
71
|
-
#end
|
72
|
-
|
73
80
|
def get_val(field)
|
74
81
|
return_val = @rally_object[field]
|
75
82
|
|
@@ -93,6 +100,11 @@ module RallyAPI
|
|
93
100
|
@rally_object[field] = object_array
|
94
101
|
end
|
95
102
|
|
103
|
+
#taken from rally_rest_api - to try to help with backwards compatibility
|
104
|
+
def camel_case_word(sym)
|
105
|
+
sym.to_s.split("_").map { |word| word.capitalize }.join
|
106
|
+
end
|
107
|
+
|
96
108
|
end
|
97
109
|
|
98
110
|
end
|
@@ -1,20 +1,28 @@
|
|
1
|
+
# :stopdoc:
|
1
2
|
#Copyright (c) 2002-2012 Rally Software Development Corp. All Rights Reserved.
|
2
3
|
#Your use of this Software is governed by the terms and conditions
|
3
4
|
#of the applicable Subscription Agreement between your company and
|
4
5
|
#Rally Software Development Corp.
|
6
|
+
# :startdoc:
|
5
7
|
module RallyAPI
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
|
9
|
+
# ===RallyAPI::RallyQuery - A helper class for making queries to Rally's REST API
|
10
|
+
# Example:
|
11
|
+
# new_query = RallyAPI::RallyQuery.new() and set query properties as needed
|
12
|
+
# --- or ---
|
13
|
+
# new_query = RallyAPI::RallyQuery.new(query_hash) with a hash of attributes<br>
|
14
|
+
# query_hash for example can be:<br>
|
15
|
+
# query_hash = {} <br>
|
16
|
+
# query_hash[:type] = Defect, Story, etc <br>
|
17
|
+
# query_hash[:query_string] = "(State = \"Closed\")" <br>
|
18
|
+
# query_hash[:fetch] = "Name,State,etc" <br>
|
19
|
+
# query_hash[:workspace] = workspace json object or ref #defaults to workspace passed in RallyRestJson.new if nil <br>
|
20
|
+
# query_hash[:project] = project json object or ref #defaults to project passed in RallyRestJson.new if nil <br>
|
21
|
+
# query_hash[:project_scope_up] = true/false <br>
|
22
|
+
# query_hash[:project_scope_down] = true/false <br>
|
23
|
+
# query_hash[:order] = "ObjectID asc" <br>
|
24
|
+
# query_hash[:page_size] <br>
|
25
|
+
# query_hash[:limit] <br>
|
18
26
|
|
19
27
|
class RallyQuery
|
20
28
|
attr_accessor :type, :query_string, :fetch, :workspace, :project, :project_scope_up, :project_scope_down
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# :stopdoc:
|
1
2
|
#Copyright (c) 2002-2012 Rally Software Development Corp. All Rights Reserved.
|
2
3
|
#Your use of this Software is governed by the terms and conditions
|
3
4
|
#of the applicable Subscription Agreement between your company and
|
4
5
|
#Rally Software Development Corp.
|
6
|
+
# :startdoc:
|
5
7
|
module RallyAPI
|
6
8
|
class RallyQueryResult
|
7
9
|
include Enumerable
|
@@ -4,29 +4,58 @@ require_relative "rally_object"
|
|
4
4
|
require_relative "rally_query"
|
5
5
|
require_relative "rally_query_result"
|
6
6
|
|
7
|
+
# --
|
7
8
|
#Copyright (c) 2002-2012 Rally Software Development Corp. All Rights Reserved.
|
8
9
|
#Your use of this Software is governed by the terms and conditions
|
9
10
|
#of the applicable Subscription Agreement between your company and
|
10
11
|
#Rally Software Development Corp.
|
12
|
+
# ++
|
13
|
+
|
14
|
+
#todo - raise exception if ws/project is not set on create?
|
15
|
+
|
16
|
+
# -----
|
17
|
+
# :title:RallyAPI
|
18
|
+
#
|
19
|
+
# ===Getting Started
|
20
|
+
# RallyAPI::RallyRestJson is the starting point for working in Ruby with Rally's REST WSAPI
|
21
|
+
#
|
22
|
+
# config = {:base_url => "https://rally1.rallydev.com/slm"}
|
23
|
+
#
|
24
|
+
# config[:username] = "user@company.com"
|
25
|
+
#
|
26
|
+
# config[:password] = "password"
|
27
|
+
#
|
28
|
+
# config[:workspace] = "Workspace Name"
|
29
|
+
#
|
30
|
+
# config[:project] = "Project Name"
|
31
|
+
#
|
32
|
+
# config[:headers] = headers #from RallyAPI::CustomHttpHeader.new()
|
33
|
+
#
|
34
|
+
# @rally = RallyAPI::RallyRestJson.new(config)
|
35
|
+
|
36
|
+
|
11
37
|
module RallyAPI
|
12
38
|
|
39
|
+
#--
|
13
40
|
#this contstant is here - a tradeoff of speed vs completeness- right now speed wins because it is so
|
14
41
|
#expensive to query typedef and read all attributes for "OBJECT" or "COLLECTION" types
|
42
|
+
#++
|
15
43
|
RALLY_REF_FIELDS = { "Subscription" => :subscription, "Workspace" => :workspace, "Project" => :project,
|
16
44
|
"Iteration" => :iteration, "Release" => :release, "WorkProduct" => :artifact,
|
17
45
|
"Requirement" => :hierarchicalrequirement, "Owner" => :user, "Tester" => :user,
|
18
46
|
"RevisionHistory" => :revisionhistory, "Revision" => :revision, "Revisions" => :revision,
|
19
47
|
"Blocker" => :artifact, "SubmittedBy" => :user, "TestCaseResult" => :testcaseresult,
|
20
|
-
"TestSet" => :testset, "Parent" => :hierarchicalrequirement, "TestFolder"=> :testfolder
|
21
|
-
|
48
|
+
"TestSet" => :testset, "Parent" => :hierarchicalrequirement, "TestFolder"=> :testfolder,
|
49
|
+
"PortfolioItemType" => :type }
|
22
50
|
|
23
51
|
|
24
|
-
#Main Class to
|
52
|
+
#Main Class to instantiate when using the tool
|
25
53
|
class RallyRestJson
|
26
|
-
DEFAULT_WSAPI_VERSION = "1.
|
54
|
+
DEFAULT_WSAPI_VERSION = "1.30"
|
27
55
|
|
28
56
|
attr_accessor :rally_url, :rally_user, :rally_password, :rally_workspace_name, :rally_project_name, :wsapi_version
|
29
57
|
attr_accessor :rally_headers, :rally_default_workspace, :rally_default_project, :low_debug, :proxy_info, :retries
|
58
|
+
attr_accessor :rally_rest_api_compat
|
30
59
|
|
31
60
|
attr_reader :rally_objects
|
32
61
|
|
@@ -40,6 +69,7 @@ module RallyAPI
|
|
40
69
|
@rally_headers = args[:headers] || CustomHttpHeader.new
|
41
70
|
@proxy_info = args[:proxy]
|
42
71
|
@retries = args[:retries] || 0
|
72
|
+
@rally_rest_api_compat = args[:rally_rest_api_compat] || false
|
43
73
|
|
44
74
|
@low_debug = args[:debug] || false
|
45
75
|
|
@@ -53,12 +83,12 @@ module RallyAPI
|
|
53
83
|
|
54
84
|
if !@rally_workspace_name.nil?
|
55
85
|
@rally_default_workspace = find_workspace(@rally_workspace_name)
|
56
|
-
raise "unable to find default workspace #{@rally_workspace_name}" if @rally_default_workspace.nil?
|
86
|
+
raise StandardError, "unable to find default workspace #{@rally_workspace_name}" if @rally_default_workspace.nil?
|
57
87
|
end
|
58
88
|
|
59
89
|
if !@rally_project_name.nil?
|
60
90
|
@rally_default_project = find_project(@rally_default_workspace, @rally_project_name)
|
61
|
-
raise "unable to find default project #{@rally_project_name}" if @rally_default_project.nil?
|
91
|
+
raise StandardError, "unable to find default project #{@rally_project_name}" if @rally_default_project.nil?
|
62
92
|
end
|
63
93
|
|
64
94
|
self
|
@@ -79,7 +109,7 @@ module RallyAPI
|
|
79
109
|
|
80
110
|
def find_project(workspace_object, project_name)
|
81
111
|
if workspace_object.nil?
|
82
|
-
raise "A workspace must be provided to find a project"
|
112
|
+
raise StandardError, "A workspace must be provided to find a project"
|
83
113
|
end
|
84
114
|
|
85
115
|
query = RallyQuery.new()
|
@@ -105,8 +135,8 @@ module RallyAPI
|
|
105
135
|
rally_type = check_type(type)
|
106
136
|
|
107
137
|
if (fields["Workspace"].nil? && fields["Project"].nil?)
|
108
|
-
fields["Workspace"] = @rally_default_workspace._ref
|
109
|
-
fields["Project"] = @rally_default_project._ref
|
138
|
+
fields["Workspace"] = @rally_default_workspace._ref unless @rally_default_workspace.nil?
|
139
|
+
fields["Project"] = @rally_default_project._ref unless @rally_default_project.nil?
|
110
140
|
end
|
111
141
|
|
112
142
|
args = {:user => @rally_user, :password => @rally_password }
|
@@ -144,23 +174,40 @@ module RallyAPI
|
|
144
174
|
RallyObject.new(self, reread({"_ref" => ref}))
|
145
175
|
end
|
146
176
|
|
147
|
-
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
|
177
|
+
##-----
|
178
|
+
#Querying Rally example
|
179
|
+
#test_query = RallyAPI::RallyQuery.new()
|
180
|
+
#test_query.type = :defect
|
181
|
+
#test_query.fetch = "Name"
|
182
|
+
#test_query.workspace = {"_ref" => "https://rally1.rallydev.com/slm/webservice/1.25/workspace/12345.js" } #optional
|
183
|
+
#test_query.project = {"_ref" => "https://rally1.rallydev.com/slm/webservice/1.25/project/12345.js" } #optional
|
184
|
+
#test_query.page_size = 200 #optional - default is 200
|
185
|
+
#test_query.limit = 1000 #optional - default is 99999
|
186
|
+
#test_query.project_scope_up = false
|
187
|
+
#test_query.project_scope_down = true
|
188
|
+
#test_query.order = "Name Asc"
|
189
|
+
#test_query.query_string = "(Severity = \"High\")"
|
190
|
+
#
|
191
|
+
#results = @rally.find(test_query)
|
192
|
+
#
|
193
|
+
##tip - set the fetch string of the query to the fields you need -
|
194
|
+
##only resort to the read method if you want your code to be slow
|
195
|
+
#results.each do |defect|
|
196
|
+
# puts defect.Name # or defect["Name"]
|
197
|
+
# defect.read #read the whole defect from Rally to get all fields (eg Severity)
|
198
|
+
# puts defect.Severity
|
199
|
+
#end
|
200
|
+
#query_obj is RallyQuery
|
201
|
+
def find(query_obj = RallyQuery.new)
|
202
|
+
yield query_obj if block_given?
|
203
|
+
|
204
|
+
if query_obj.workspace.nil?
|
205
|
+
query_obj.workspace = @rally_default_workspace unless @rally_default_workspace.nil?
|
206
|
+
end
|
207
|
+
|
161
208
|
errs = query_obj.validate(@rally_objects)
|
162
209
|
if errs.length > 0
|
163
|
-
raise "Errors making Rally Query: #{errs.to_s}"
|
210
|
+
raise StandardError, "Errors making Rally Query: #{errs.to_s}"
|
164
211
|
end
|
165
212
|
|
166
213
|
query_url = make_query_url(@rally_url, @wsapi_version, check_type(query_obj.type))
|
@@ -195,6 +242,30 @@ module RallyAPI
|
|
195
242
|
RallyObject.new(self, update["Object"])
|
196
243
|
end
|
197
244
|
|
245
|
+
def allowed_values(type, field)
|
246
|
+
if type.class == Symbol
|
247
|
+
query_type = @rally_objects[type]
|
248
|
+
else
|
249
|
+
query_type = type
|
250
|
+
end
|
251
|
+
type_defs_query = RallyQuery.new()
|
252
|
+
type_defs_query.type = :typedefinition
|
253
|
+
type_defs_query.fetch = true
|
254
|
+
type_defs_query.query_string= "(Name = \"#{query_type}\")"
|
255
|
+
type_defs = find(type_defs_query)
|
256
|
+
|
257
|
+
allowed_vals = {}
|
258
|
+
type_defs[0]["Attributes"].each do |attr|
|
259
|
+
next if attr["ElementName"] != field
|
260
|
+
attr["AllowedValues"].each do |val_ref|
|
261
|
+
val = val_ref["StringValue"]
|
262
|
+
val = "Null" if val.nil? || val.empty?
|
263
|
+
allowed_vals[val] = true
|
264
|
+
end
|
265
|
+
end
|
266
|
+
allowed_vals
|
267
|
+
end
|
268
|
+
|
198
269
|
private
|
199
270
|
|
200
271
|
def make_get_url(type)
|
@@ -220,9 +291,9 @@ module RallyAPI
|
|
220
291
|
|
221
292
|
def check_type(type_name)
|
222
293
|
if @rally_objects[type_name].nil?
|
223
|
-
raise "The object type #{type_name} is not valid for the wsapi"
|
294
|
+
raise StandardError, "The object type #{type_name} is not valid for the wsapi"
|
224
295
|
end
|
225
|
-
@rally_objects[type_name]
|
296
|
+
@rally_objects[type_name].gsub(" ", "") #for wsapi no space is expected
|
226
297
|
end
|
227
298
|
|
228
299
|
#ref should be like https://rally1.rallydev.com/slm/webservice/1.25/defect/12345.js
|
@@ -282,16 +353,16 @@ module RallyAPI
|
|
282
353
|
type_defs = find(type_defs_query)
|
283
354
|
type_defs.each do |td|
|
284
355
|
type_sym = td.Name.downcase.gsub(" ", "").to_sym
|
285
|
-
@rally_objects[type_sym] = td.Name
|
356
|
+
@rally_objects[type_sym] = td.Name
|
286
357
|
end
|
287
358
|
|
288
359
|
#some convenience keys to help people - someday we'll fix the api and make HR called story
|
289
360
|
@rally_objects[:artifact] = "Artifact"
|
290
|
-
@rally_objects[:persistableobject] = "
|
291
|
-
@rally_objects[:useriterationcapacity] = "
|
292
|
-
@rally_objects[:userpermission] = "
|
293
|
-
@rally_objects[:story] = "
|
294
|
-
@rally_objects[:userstory] = "
|
361
|
+
@rally_objects[:persistableobject] = "Persistable Object"
|
362
|
+
@rally_objects[:useriterationcapacity] = "User Iteration Capacity"
|
363
|
+
@rally_objects[:userpermission] = "User Permission"
|
364
|
+
@rally_objects[:story] = "Hierarchical Requirement"
|
365
|
+
@rally_objects[:userstory] = "Hierarchical Requirement"
|
295
366
|
|
296
367
|
end
|
297
368
|
|
data/lib/rally_api/version.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# :nodoc:
|
1
2
|
#Copyright (c) 2002-2012 Rally Software Development Corp. All Rights Reserved.
|
2
3
|
#Your use of this Software is governed by the terms and conditions
|
3
4
|
#of the applicable Subscription Agreement between your company and
|
4
5
|
#Rally Software Development Corp.
|
5
6
|
module RallyAPI
|
6
|
-
VERSION = "0.
|
7
|
+
VERSION = "0.5.0"
|
7
8
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rally_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-28 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
16
|
-
requirement: &
|
16
|
+
requirement: &70134702100760 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: 1.6.7
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70134702100760
|
25
25
|
description: API wrapper for Rally's JSON REST web services api
|
26
26
|
email:
|
27
27
|
- dsmith@rallydev.com
|
@@ -32,12 +32,12 @@ files:
|
|
32
32
|
- README.rdoc
|
33
33
|
- Rakefile
|
34
34
|
- lib/rally_api/custom_http_header.rb
|
35
|
+
- lib/rally_api/lookback_api_query.rb
|
35
36
|
- lib/rally_api/rally_json_connection.rb
|
36
37
|
- lib/rally_api/rally_object.rb
|
37
38
|
- lib/rally_api/rally_query.rb
|
38
39
|
- lib/rally_api/rally_query_result.rb
|
39
40
|
- lib/rally_api/rally_rest_json.rb
|
40
|
-
- lib/rally_api/time_machine_query.rb
|
41
41
|
- lib/rally_api/version.rb
|
42
42
|
- lib/rally_api.rb
|
43
43
|
homepage: http://developer.rallydev.com/help
|