Class: RestBuilder
- Inherits:
-
Object
- Object
- RestBuilder
- Defined in:
- lib/rally_rest_api/rest_builder.rb
Overview
:nodoc:
Direct Known Subclasses
Constant Summary collapse
- COLLECTION_TYPES =
[:tags, :dependents, :dependencies, :defects, :duplicates, :children, :predecessors, :test_cases, :artifacts, :change_sets]
Instance Attribute Summary collapse
-
#base_url ⇒ Object
readonly
Returns the value of attribute base_url.
-
#http_headers ⇒ Object
readonly
Returns the value of attribute http_headers.
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#password ⇒ Object
readonly
Returns the value of attribute password.
-
#username ⇒ Object
readonly
Returns the value of attribute username.
Instance Method Summary collapse
-
#builder_block(args) ⇒ Object
Because we are adapting to the xml builder as such: We say to the RallyRestAPI: slm.create(:feature, :name => “feature name”).
- #camel_case_word(sym) ⇒ Object
- #check_for_errors(response) ⇒ Object
- #collection_type?(type) ⇒ Boolean
-
#convert_arg_for_builder(value) ⇒ Object
Convert the values of the hash passed to the RestApi appropiatly RestObject –> a hash with the ref value nil –> “null” ref values Time –> iso8601 time strings Arrays of RestObjects –> block that has a nested xml value.
- #create_builder ⇒ Object
-
#create_rest(artifact_type, args, username, password) ⇒ Object
create_rest - convert slm builder style: slm.create(:feature, :name => “feature name”).
- #debug(message) ⇒ Object
- #delete_rest(ref_url, username, password) ⇒ Object
-
#initialize(base_url, username, password, version = "current", http_headers = CustomHttpHeader.new) ⇒ RestBuilder
constructor
A new instance of RestBuilder.
- #marshal_dump ⇒ Object
- #marshal_load(stuff) ⇒ Object
- #post_xml(url, xml, username, password) ⇒ Object
- #read_rest(ref_url, username, password) ⇒ Object
- #send_request(url, req, username, password) ⇒ Object
-
#update_rest(artifact_type, url, args, username, password) ⇒ Object
update_rest - convert slm builder style: feature.update(:name => “feature name”).
Constructor Details
#initialize(base_url, username, password, version = "current", http_headers = CustomHttpHeader.new) ⇒ RestBuilder
Returns a new instance of RestBuilder.
12 13 14 |
# File 'lib/rally_rest_api/rest_builder.rb', line 12 def initialize(base_url, username, password, version = "current", http_headers = CustomHttpHeader.new) @base_url, @username, @password, @version, @http_headers = base_url, username, password, version, http_headers end |
Instance Attribute Details
#base_url ⇒ Object (readonly)
Returns the value of attribute base_url.
9 10 11 |
# File 'lib/rally_rest_api/rest_builder.rb', line 9 def base_url @base_url end |
#http_headers ⇒ Object (readonly)
Returns the value of attribute http_headers.
9 10 11 |
# File 'lib/rally_rest_api/rest_builder.rb', line 9 def http_headers @http_headers end |
#logger ⇒ Object
Returns the value of attribute logger.
10 11 12 |
# File 'lib/rally_rest_api/rest_builder.rb', line 10 def logger @logger end |
#password ⇒ Object (readonly)
Returns the value of attribute password.
9 10 11 |
# File 'lib/rally_rest_api/rest_builder.rb', line 9 def password @password end |
#username ⇒ Object (readonly)
Returns the value of attribute username.
9 10 11 |
# File 'lib/rally_rest_api/rest_builder.rb', line 9 def username @username end |
Instance Method Details
#builder_block(args) ⇒ Object
Because we are adapting to the xml builder as such:
We say to the RallyRestAPI:
slm.create(:feature, :name => "feature name")
We tell the xml builder:
b.feature {
b.name("feature name")
}
in the case where one element is a collection, RallyRest would look like
slm.create(:feature, :name => "name", :dependancies => [sr1, sr2])
This needs to be converted to
b.feature {
b.name("name")
b.Dependancies {
b.SupplementalRequirement(:ref => "http://....")
b.SupplementalRequirement(:ref => "http://....")
}
}
in this case we need to create a block to handle the nested calls (b.Supp…)
There are also nested/complex values, for example slm.create(:defect, :web_link => => “123”, :description => “foo” )
b.defect {
b.web_link {
b.id "123"
b.description "foo"
}
}
We need to convert the args hash into a block that can be fed to the builder. This will send the keys of the map as “methods” (b.name) and the values of map as the arguments to the method (“feature name”).
Additionally we camel-case the elements (as JDOM can’t handle elements case free). #convert_arg_for_builder will convert the value portion of the hash to the appropiate string, or block for the xml builder
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/rally_rest_api/rest_builder.rb', line 159 def builder_block(args) sort_block = lambda { |a,b| a.to_s <=> b.to_s } # Sort the keys, for testing lambda do |builder| args.sort(&sort_block).each do |(attr, value)| if COLLECTION_TYPES.include? attr # The call to builder with only a type and a block needs to be marked as such # note the '&' builder.__send__(camel_case_word(attr), &convert_arg_for_builder([value].flatten)) elsif value.instance_of? Hash builder.__send__(camel_case_word(attr), &builder_block(value)) else builder.__send__(camel_case_word(attr), convert_arg_for_builder(value)) end end end end |
#camel_case_word(sym) ⇒ Object
114 115 116 |
# File 'lib/rally_rest_api/rest_builder.rb', line 114 def camel_case_word(sym) sym.to_s.split("_").map { |word| word.capitalize }.join end |
#check_for_errors(response) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/rally_rest_api/rest_builder.rb', line 102 def check_for_errors(response) case response when Net::HTTPUnauthorized raise Rally::NotAuthenticatedError.new("Invalid Username or Password.") else s = response.body document = REXML::Document.new s node = REXML::XPath.first document, '//Errors' raise node.to_s if node && node.has_elements? end end |
#collection_type?(type) ⇒ Boolean
204 205 206 |
# File 'lib/rally_rest_api/rest_builder.rb', line 204 def collection_type?(type) COLLECTION_TYPES.include?(type) end |
#convert_arg_for_builder(value) ⇒ Object
Convert the values of the hash passed to the RestApi appropiatly RestObject –> a hash with the ref value nil –> “null” ref values Time –> iso8601 time strings Arrays of RestObjects –> block that has a nested xml value
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/rally_rest_api/rest_builder.rb', line 182 def convert_arg_for_builder(value) case value when RestObject { :ref => value.ref } when NilClass { :ref => "null"} when Time value.iso8601 when Array lambda do |builder| value.each do |rest_object| builder.__send__(rest_object.type, convert_arg_for_builder(rest_object)) end end else value end end |
#create_builder ⇒ Object
96 97 98 99 100 |
# File 'lib/rally_rest_api/rest_builder.rb', line 96 def create_builder b = Builder::XmlMarkup.new b.instruct! b end |
#create_rest(artifact_type, args, username, password) ⇒ Object
create_rest - convert slm builder style:
slm.create(:feature, :name => "feature name")
Into xml builder style:
b.feature {
b.name("feature name")
}
then call create on the REST api
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rally_rest_api/rest_builder.rb', line 32 def create_rest(artifact_type, args, username, password) type = camel_case_word(artifact_type) debug "RestBuilder#create_rest artifact_type = #{type}" b = create_builder xml = b.__send__(type, &builder_block(args)) result = post_xml("#{self.base_url}/webservice/#{@version}/#{type}/create", xml, username, password) doc = REXML::Document.new result doc.root.elements["Object"].to_s end |
#debug(message) ⇒ Object
208 209 210 |
# File 'lib/rally_rest_api/rest_builder.rb', line 208 def debug() @logger.debug if @logger end |
#delete_rest(ref_url, username, password) ⇒ Object
66 67 68 69 70 71 |
# File 'lib/rally_rest_api/rest_builder.rb', line 66 def delete_rest(ref_url, username, password) debug "RestBuilder#delete_rest ref_url = #{ref_url} username = #{ username } pass = #{ password }" url = URI.parse(ref_url) req = Net::HTTP::Delete.new(url.path) send_request(url, req, username, password) end |
#marshal_dump ⇒ Object
16 17 18 |
# File 'lib/rally_rest_api/rest_builder.rb', line 16 def marshal_dump [@username, @password, @base_url, @version] end |
#marshal_load(stuff) ⇒ Object
20 21 22 |
# File 'lib/rally_rest_api/rest_builder.rb', line 20 def marshal_load(stuff) @username, @password, @base_url, @version = *stuff end |
#post_xml(url, xml, username, password) ⇒ Object
73 74 75 76 77 78 79 |
# File 'lib/rally_rest_api/rest_builder.rb', line 73 def post_xml(url, xml, username, password) debug "RestBuilder#post_xml xml = #{xml} as user #{ self.username } pass = #{ self.password }" url = URI.parse(url) req = Net::HTTP::Post.new(url.path) req.body = xml send_request(url, req, username, password) end |
#read_rest(ref_url, username, password) ⇒ Object
59 60 61 62 63 64 |
# File 'lib/rally_rest_api/rest_builder.rb', line 59 def read_rest(ref_url, username, password) debug "RestBuilder#read_rest ref_url = #{ref_url} username = #{ username } pass = #{ password }" url = URI.parse(ref_url) req = Net::HTTP::Get.new(url.path + (url.query ? "?" + url.query : "")) send_request(url, req, username, password) end |
#send_request(url, req, username, password) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/rally_rest_api/rest_builder.rb', line 81 def send_request(url, req, username, password) @http_headers.add_headers(req) req.basic_auth username, password req.content_type = 'text/xml' proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : OpenStruct.new http = Net::HTTP.new(url.host, url.port, proxy.host, proxy.port, proxy.user, proxy.password) http.use_ssl = true if url.scheme == "https" http.verify_mode = OpenSSL::SSL::VERIFY_NONE debug "RestBuilder#send_request req = #{req.inspect} -- #{url}" response = http.start { |http| http.request(req) } debug "RestBuilder#send_request result = #{response.body}" check_for_errors(response) response.body end |
#update_rest(artifact_type, url, args, username, password) ⇒ Object
update_rest - convert slm builder style:
feature.update(:name => "feature name")
Into xml builder style:
b.feature(:ref => "http://...") {
b.name("feature name")
}
then call create on the REST api
51 52 53 54 55 56 57 |
# File 'lib/rally_rest_api/rest_builder.rb', line 51 def update_rest(artifact_type, url, args, username, password) debug "RestBuilder#update_rest url = #{url}" b = create_builder # and pass that to the builder xml = b.__send__(artifact_type, :ref => url, &builder_block(args)) post_xml(url, xml, username, password) end |