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, :changesets]
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.
64 65 66 |
# File 'lib/rally_rest_api/rest_builder.rb', line 64 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.
61 62 63 |
# File 'lib/rally_rest_api/rest_builder.rb', line 61 def base_url @base_url end |
#http_headers ⇒ Object (readonly)
Returns the value of attribute http_headers.
61 62 63 |
# File 'lib/rally_rest_api/rest_builder.rb', line 61 def http_headers @http_headers end |
#logger ⇒ Object
Returns the value of attribute logger.
62 63 64 |
# File 'lib/rally_rest_api/rest_builder.rb', line 62 def logger @logger end |
#password ⇒ Object (readonly)
Returns the value of attribute password.
61 62 63 |
# File 'lib/rally_rest_api/rest_builder.rb', line 61 def password @password end |
#username ⇒ Object (readonly)
Returns the value of attribute username.
61 62 63 |
# File 'lib/rally_rest_api/rest_builder.rb', line 61 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
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/rally_rest_api/rest_builder.rb', line 220 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
175 176 177 |
# File 'lib/rally_rest_api/rest_builder.rb', line 175 def camel_case_word(sym) sym.to_s.split("_").map { |word| word.capitalize }.join end |
#check_for_errors(response) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/rally_rest_api/rest_builder.rb', line 162 def check_for_errors(response) case response when Net::HTTPUnauthorized raise Rally::NotAuthenticatedError.new("Invalid Username or Password.") else #s = response.body s = response.plain_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
265 266 267 |
# File 'lib/rally_rest_api/rest_builder.rb', line 265 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
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/rally_rest_api/rest_builder.rb', line 243 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
156 157 158 159 160 |
# File 'lib/rally_rest_api/rest_builder.rb', line 156 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
84 85 86 87 88 89 90 91 92 93 |
# File 'lib/rally_rest_api/rest_builder.rb', line 84 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
269 270 271 |
# File 'lib/rally_rest_api/rest_builder.rb', line 269 def debug() @logger.debug if @logger end |
#delete_rest(ref_url, username, password) ⇒ Object
118 119 120 121 122 123 |
# File 'lib/rally_rest_api/rest_builder.rb', line 118 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
68 69 70 |
# File 'lib/rally_rest_api/rest_builder.rb', line 68 def marshal_dump [@username, @password, @base_url, @version] end |
#marshal_load(stuff) ⇒ Object
72 73 74 |
# File 'lib/rally_rest_api/rest_builder.rb', line 72 def marshal_load(stuff) @username, @password, @base_url, @version = *stuff end |
#post_xml(url, xml, username, password) ⇒ Object
125 126 127 128 129 130 131 |
# File 'lib/rally_rest_api/rest_builder.rb', line 125 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
111 112 113 114 115 116 |
# File 'lib/rally_rest_api/rest_builder.rb', line 111 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
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/rally_rest_api/rest_builder.rb', line 133 def send_request(url, req, username, password) @http_headers.add_headers(req) req.basic_auth username, password req.content_type = 'text/xml' req.add_field('Accept-Encoding', 'gzip, deflate') 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 http.read_timeout = 300 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 debug "RestBuilder#send_request result = #{response.plain_body}" headerstr = "" response.each_header { |k,v| headerstr << "#{k}--#{v}|" } debug "RestBuilder#send_request result headers = #{headerstr} and length is #{response.plain_body.length}" check_for_errors(response) response.plain_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
103 104 105 106 107 108 109 |
# File 'lib/rally_rest_api/rest_builder.rb', line 103 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 |