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 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
- require 'rally_api'
20
-
21
- #Setting custom headers
22
- headers = RallyAPI::CustomHttpHeader.new()
23
- headers.name = "My Utility"
24
- headers.vendor = "MyCompany"
25
- headers.version = "1.0"
26
-
27
- #==================== Making a connection to Rally ====================
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
- #==================== Querying Rally ==========================
38
- test_query = RallyAPI::RallyQuery.new()
39
- test_query.type = :defect
40
- test_query.fetch = "Name"
41
- test_query.workspace = {"_ref" => "https://rally1.rallydev.com/slm/webservice/1.25/workspace/12345.js" } #optional
42
- test_query.project = {"_ref" => "https://rally1.rallydev.com/slm/webservice/1.25/project/12345.js" } #optional
43
- test_query.page_size = 200 #optional - default is 200
44
- test_query.limit = 1000 #optional - default is 99999
45
- test_query.project_scope_up = false
46
- test_query.project_scope_down = true
47
- test_query.order = "Name Asc"
48
- test_query.query_string = "(Severity = \"High\")"
49
-
50
- results = @rally.find(test_query)
51
-
52
- #tip - set the fetch string of the query to the fields you need -
53
- #only resort to the read method if you want your code to be slow
54
- results.each do |defect|
55
- puts defect.Name
56
- defect.read #read the whole defect from Rally to get all fields (eg Severity)
57
- puts defect.Severity
58
- end
59
-
60
- #==================== Reading an Artifact ====================
61
- defect = @rally.read(:defect, 12345) #by ObjectID
62
- #or
63
- defect = @rally.read(:defect, "FormattedID|DE42") #by FormattedID
64
- #or if you already have an object like from a query
65
- results = @rally.find(RallyAPI::RallyQuery.new({:type => :defect, :query_string => "(FormattedID = DE42)"}))
66
- defect = results.first
67
- defect.read
68
-
69
- puts defect["Name"]
70
- #or - fields can be read by bracket artifact["FieldDisplayName"] or artifact.FieldDisplayName
71
- puts defect.Name
72
-
73
- #An Important note about reading fields and fetching:
74
- #If you query with a specific fetch string, for example query defect and fetch Name,Severity,Description
75
- #You will *only* get back those fields defect.Priority will be nil, but may not be null in Rally
76
- #Use object.read or @rally.read to make sure you read the whole object if you want what is in Rally
77
- # This is done for speed - lazy loading (going back to get a value from Rally) can be unneccessarily slow
78
- # *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.
79
-
80
- #==================== Creating an Artifact ====================
81
- obj = {}
82
- obj["Name"] = "Test Defect created #{DateTime.now()}"
83
- new_de = @rally.create(:defect, obj)
84
- puts new_de["FormattedID"]
85
-
86
- #==================== Updating an Artifact ====================
87
- fields = {}
88
- fields["Severity"] = "Critical"
89
- fields["Description"] = "Description for the issue"
90
- updated_defect = @rally.update(:defect, 12345, fields) #by ObjectID
91
- #or
92
- updated_defect = @rally.update(:defect, "FormattedID|DE42", fields) #by FormattedID
93
- # or
94
- defect = @rally.read(:defect, 12345) #by lookup then udpating via the object
95
- field_updates = {"Description" => "Changed Description"}
96
- defect.update(field_updates)
97
-
98
-
99
- #== License
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[:type] = Defect, Story, etc
9
- # query_hash[:query_string] = "(State = \"Closed\")"
10
- # query_hash[:fetch] = "Name,State,etc"
11
- # query_hash[:workspace] = workspace json object or ref #defaults to workspace passed in RallyRestJson.new if nil
12
- # query_hash[:project] = project json object or ref #defaults to project passed in RallyRestJson.new if nil
13
- # query_hash[:project_scope_up] = true/false
14
- # query_hash[:project_scope_down] = true/false
15
- # query_hash[:order] = "ObjectID asc"
16
- # query_hash[:page_size]
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
- #query_params[:query] = @query_string
30
- #query_params[:fetch] = @fetch
31
- query_params[:workspace] = @workspace["_ref"] if !@workspace.nil?
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
- # query is like:
7
- # query_hash = {}
8
- # query_hash[:type] = Defect, Story, etc
9
- # query_hash[:query_string] = "(State = \"Closed\")"
10
- # query_hash[:fetch] = "Name,State,etc"
11
- # query_hash[:workspace] = workspace json object or ref #defaults to workspace passed in RallyRestJson.new if nil
12
- # query_hash[:project] = project json object or ref #defaults to project passed in RallyRestJson.new if nil
13
- # query_hash[:project_scope_up] = true/false
14
- # query_hash[:project_scope_down] = true/false
15
- # query_hash[:order] = "ObjectID asc"
16
- # query_hash[:page_size]
17
- # query_hash[:stopafter]
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 create from when using the tool
52
+ #Main Class to instantiate when using the tool
25
53
  class RallyRestJson
26
- DEFAULT_WSAPI_VERSION = "1.25"
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
- #query_hash is a has like:
148
- # query_hash = {}
149
- # query_hash[:type] = Defect, Story, etc
150
- # query_hash[:query_string] = "(State = \"Closed\")"
151
- # query_hash[:fetch] = "Name,State,etc"
152
- # query_hash[:workspace] = workspace json object or ref #defaults to workspace passed in RallyRestJson.new if nil
153
- # query_hash[:project] = project json object or ref #defaults to project passed in RallyRestJson.new if nil
154
- # query_hash[:project_scope_up] = true/false
155
- # query_hash[:project_scope_down] = true/false
156
- # query_hash[:order] = "ObjectID asc"
157
- # query_hash[:pagesize]
158
- # query_hash[:stopafter]
159
- #todo default workspace and project if not set?
160
- def find(query_obj)
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.gsub(" ","")
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] = "PersistableObject"
291
- @rally_objects[:useriterationcapacity] = "UserIterationCapacity"
292
- @rally_objects[:userpermission] = "UserPermission"
293
- @rally_objects[:story] = "HierarchicalRequirement"
294
- @rally_objects[:userstory] = "HierarchicalRequirement"
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
 
@@ -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.4.1"
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.1
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-03-01 00:00:00.000000000Z
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: &70105132306080 !ruby/object:Gem::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: *70105132306080
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